Автор Тема: Приспособим PureBuilder для разработки игр  (Прочитано 42917 раз)

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #45 : Февраль 23, 2011, 09:14:17 pm »
1.Необходимость больше писать приведёт к тому, что фишкой не будут пользоваться. Перепишите пример со структурами и сравните. Вспомните хотя бы, как сишники жалуются на "многословность" синтаксиса Оберона.

Ну вот я пишу на питоне тоже, там есть родные (лаконичные) кортежи. Пользуюсь ими все равно не очень часто (хотя пишу в обсуждаемом стиле - все инициализируется чем-то осмысленным). Основной недостаток - если такой кортеж пошел гулять за пределы двух/трех функций, то понять смысл того, что там лежит становится трудно. Именованная структура все же лучше. Опять же - ваш оригинальный пример довольно экстремальный :) Так что острой необходимости в кортежах я не вижу.
А в питоне разве содержимое кортэжа мутабельно?
Собственно у питона две беды -- динамическая типизация и мутабельность данных :-)
Скажем в haskell'a я часто пользуюсь кортежами, и проблем с пониманием того, что там лежит обычно не возникает -- типизация то строгая статическая.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #46 : Февраль 23, 2011, 09:49:32 pm »
А в питоне разве содержимое кортэжа мутабельно?
Собственно у питона две беды -- динамическая типизация и мутабельность данных :-)

Да, динамическая типизация усугубляет. Но у меня и в С++ такая же проблема. Начинает ходить такая тупла с двумя int. И фиг сходу скажешь - чего ж там за int'ы и какой из них тебе нужен.

Цитировать
Скажем в haskell'a я часто пользуюсь кортежами, и проблем с пониманием того, что там лежит обычно не возникает -- типизация то строгая статическая.

Если в языке кортеж это больше, чем анонимная структура с анонимными полями - то наверное из нее можно выжать что-то сильно полезное. Например, если представить, что в нашем случае список инициализации - это на самом деле кортеж. Или пойти еще дальше: вызов функции это на самом деле вызов функции с одним аргументом - кортежем. Но я пока не готов настолько глубоко копать...

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #47 : Февраль 23, 2011, 11:30:01 pm »
Отрицательный результат - тоже результат. И хотя нас часто порывает принять за данность выполнение программы в идеальном окружении с идеальным пользователем, а всю логику обработки ошибок закинуть как можно выше, это не выход.

Классный выход. Настолько классный, что в любом распространенном ЯП уровнем выше С в каком-то виде присутствует альтернатива "отрицательным" результатам. Даже в хаскеле - при том, что там нет исключений - зато есть монады :)

Цитата: Berserker
Пора уже понять, что практически все функции не способны гарантировать результат.

Поняли - и придумали исключения, чтобы обойти эту проблему :) Теперь все функции могут гарантировать "положительный" результат, потому что "отрицательный" передается отдельно.

Цитата: Berserker
Что исключения одного класса обезличиваются при всплывании, превращаясь в нечто вроде TIOError. Что если мы хотим обработать 250 вызовов функций по-разному, нам понадобятся 250 обработчиков и их логика должна быть на том же уровне, что и вызов функций.

Они не обезличиваются. Это вы абстрагируетесь от конкретного типа, по всем правилам ООП. Хотите обработать 250 исключений по-разному - пожалуйста. Никто этого не делает, потому что никому это не надо :)
Логика обработки не может быть на одном уровне - иначе вы не сможете переиспользовать один и тот же код. Функция чтения файла не может знать, что ей делать с ошибкой открытия файла. Это может знать только конкретная операция, например операция открытия документа или операция чтения данных из файлового кэша. В одном случае документ не может быть открыт и пользователь получает внятную ошибку. В другом - данные берутся из оригинального источника и кладутся в кэш. В обоих случаях между "верхом" операции и функцией чтения файла в стэке могут быть десятки слоев абстракции, которым нафиг не нужна возня с такой ошибкой, они хотят делать свою работу.

Цитата: Berserker
С какой кстати высший уровень должен знать все типы исключений низших, а если не знать, то иметь лишь единственный молчаливый способ их обработать?

Действительно, с какой кстати? И почему единственный? Сколько надо - столько и сделаем. Обычно достаточно единичных обработчиков на кучу кода. И почему молчаливый? Как захотим - так и сделаем.
« Последнее редактирование: Февраль 23, 2011, 11:31:58 pm от vlad »

Илья Ермаков

  • Full Member
  • ***
  • Сообщений: 177
    • Просмотр профиля
    • OberonCore
Re:Приспособим PureBuilder для разработки игр
« Ответ #48 : Февраль 24, 2011, 05:50:23 pm »
Если в языке кортеж это больше, чем анонимная структура с анонимными полями - то наверное из нее можно выжать что-то сильно полезное. Например, если представить, что в нашем случае список инициализации - это на самом деле кортеж. Или пойти еще дальше: вызов функции это на самом деле вызов функции с одним аргументом - кортежем. Но я пока не готов настолько глубоко копать...

В JavaScript во многих библиотеках (Rich Web и т.п., например, Qooxdoo) функции часто параметризуются объектами.
Т.е. типа: var panel = new qx.ui....Panel({width: 200, height: 300}).
Вообще, достаточно удобно и единообразно получается.

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #49 : Февраль 24, 2011, 06:03:09 pm »
Вообще, у например F# все функции внешних .нет либ вызываются именно как функция с одним аргументом-картежем значений.
mFile.MenuItems.Add(miOpen)

Тут (miOpen) это именно что кортеж с одним элементом внутри. Нормальный вызов функции с параметром-не кортежем в F# выглядит так:
mFile.MenuItems.Add miOpen
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #50 : Март 02, 2011, 06:34:39 pm »
Цитировать
Ну вот я пишу на питоне тоже, там есть родные (лаконичные) кортежи. Пользуюсь ими все равно не очень часто (хотя пишу в обсуждаемом стиле - все инициализируется чем-то осмысленным).
Основной недостаток - если такой кортеж пошел гулять за пределы двух/трех функций, то понять смысл того, что там лежит становится трудно.
Именованная структура все же лучше. Опять же - ваш оригинальный пример довольно экстремальный. Так что острой необходимости в кортежах я не вижу.
Нет ничего экстремального в инициализации по одному условию нескольких переменных и по смыслу не объединяемых в одну сущность. Ну, строго говоря, острой необходимости нет не только в кортежах, но и в...



Цитировать
Цитировать
Как минимум нужно и объявление типа по месту.
В смысле рядом с функцией? Ну да, желательно. Но тоже не то, чтобы принципиально, если модули человеческих размеров.
Модули даже человеческих размеров всё-таки велики. Вспомните как сишники жалуются, что в Паскале до переменных в функции долго добираться, а Вы аж про модули. Впрочем, записи,
нужные лишь в одной процедуре, можно объявить в ней самой, это давно есть.


Цитировать
Цитировать
статически объявленные экземпляры структур
Ну так - инициализировать при объявлении. Что не так?
Как, что? Для функций, возвращающих большие структуры, возникают большие накладные расходы на копирование. То же касается и массивов. Это можно обойти, но неизбежно вылезут другие шутки.

Цитировать
Цитировать
Точно ничего? А выделять память отдельной операцией будете? Чем поможет вспомогательная функция-конструктор, если инициализировать всё равно одной командой нужно? Как инициализировать расширенные записи при желании использовать код для базовых записей?
Ну, допустим у нас есть такой синтаксис для инициализации:...
И опять-таки, большие накладные расходы, особенно для инициализации больших структур с серией маленьких расширений. Если это устраивает, то можно и без конструкторов.
Хотя смысл статически выделенных данных по большей части в скорости работы с ними. Если она не нужна, то и статические данные не нужны, о чём я и писал. Понятное дело, что в
задачах, где хватает Питона, разработчика такое может не волновать.
И это не единственные последствия, но лень писать, ибо длинно.
Да, и всё-таки, как поможет функция-конструктор для большой структуры, если инициализировать всё-равно одной операцией?

Цитировать
Просто данные модуля инициализируются так же как и локальные переменные - при объявлении. Инициализация таких данных происходит до вызова секции инициализации модуля.
Нет, я имел ввиду ситуацию, когда нужно инициализировать именно в секции модуля, но мы знаем точно, что она там происходит, тем не менее везде нужно будет использовать проверку об инициализации.
Про вред размазывания инициализации по тексту модуля я уже писал когда-то, сейчас лениво, да и тогда Вам не показалось это чем-то важным.

Цитировать
Цитировать
К примеру, транспонирование матрицы - штука быстрая. А если это массив структур, содержащих массивы?
Не, хочется реального примера Мне больше видятся всякие низкоуровневые штуки, когда надо скормить кусок памяти драйверу и т.п. Но для таких случае всегда есть SYSTEM Улыбающийся
Во первых, инициализация - это за исключением наиболее простых случаев, не забитие одним и тем же значеним всего массива. Ну а возможность в оригинальном Обероне объявить большой массив записей вместе с потенциальной необходимостью тут же инициализировать эти записи вообще порождает курьёзную ситуацию.
Как пример, представьте себе большой массив, который заполняется по мере надобности и который нужно получить с минимальной задержкой, чтобы без промедлений отреагировать на действия пользователя.
Давать что-то более конкретно - лень.

Цитировать
Цитировать
... а вот функции по нескольку тысяч строк, плохо поддающиеся пониманию и переработке из-за усеянности на самом деле ненужными return-ами мне встречаются регулярно.
Дык, согласитесь, что оригинальная проблема в функциях на 1000 строк, а не в RETURN. Думаю вы бы скорее согласились сопровождать функции на 10 строк с RETURN, чем на 1000 строк без RETURN?
Проблема именно во множественных return, а также break, continue, goto, ну и головах программистах, естественно. Дело в сопровождении. Сначала функция хоть и с несколькими выходами, но небольшая, ничего криминального. Со временем функция разрастается и пора бы её разбить на множество функций, да в общем случае сделать это не так просто, поскольку return в подфункцию не засунешь, а использование механизма исключений(там где он вообще есть) только закрепит кашу, пусть и разбитую на порции. Заодно это требует от исключений быть гибкими (переносить что угодно) и быстрыми(поскольку в переходы часто закладывается нормальная логика, а не только маловероятные исключения). Легко такое сделать? Что нам об этом говорит опыт С++, Java, C#?

Цитировать
Человеком ваш код тоже воспринимается непросто. Лично мне понятнее переделанный вариант.
А мне - мой, что тут поделать.

Вспомнил о ещё одной неудобности. В Обероне значение переменных можно менять, передавая их через параметры в процедуры. Легко представить ситуацию, когда такими процедурами можно также инциализировать, но при таком подходе получится это только с накладными расходами.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #51 : Март 03, 2011, 11:51:33 pm »
Цитировать
Опять же - ваш оригинальный пример довольно экстремальный. Так что острой необходимости в кортежах я не вижу.
Нет ничего экстремального в инициализации по одному условию нескольких переменных и по смыслу не объединяемых в одну сущность. Ну, строго говоря, острой необходимости нет не только в кортежах, но и в...

Ну вот не знаю. В моем коде таких ситуаций (инициализация разных переменных по условию с последующим использованием этих переменных по другому условию) - не встречается. Хотите верьте - хотите нет. И я считаю такой код трудным для чтения - вместо плавного перетекания от одного к другому имеем рваные условия с возможностью запутаться - что, откуда и куда.

Цитировать
Ну так - инициализировать при объявлении. Что не так?
Как, что? Для функций, возвращающих большие структуры, возникают большие накладные расходы на копирование. То же касается и массивов. Это можно обойти, но неизбежно вылезут другие шутки.

Не, не понимаю, о каком копировании речь? Код "X x = f();" всегда может быть автоматически сведен к "X x; f(x);". Если, конечно, не пытаться повторять плюсовую семантику с конструкторами копирования и т.д.

Да, и всё-таки, как поможет функция-конструктор для большой структуры, если инициализировать всё-равно одной операцией?

Не, не понимаю в чем проблема...

Цитировать
Просто данные модуля инициализируются так же как и локальные переменные - при объявлении. Инициализация таких данных происходит до вызова секции инициализации модуля.
Нет, я имел ввиду ситуацию, когда нужно инициализировать именно в секции модуля, но мы знаем точно, что она там происходит, тем не менее везде нужно будет использовать проверку об инициализации.

Какая-то надуманная ситуация. Почему именно в секции модуля?

Про вред размазывания инициализации по тексту модуля я уже писал когда-то, сейчас лениво, да и тогда Вам не показалось это чем-то важным.

Да никто ж не заставляет размазывать. Пропишите непосредственно перед секцией. Можно даже потребовать на уровне компилятора.

Во первых, инициализация - это за исключением наиболее простых случаев, не забитие одним и тем же значеним всего массива. Ну а возможность в оригинальном Обероне объявить большой массив записей вместе с потенциальной необходимостью тут же инициализировать эти записи вообще порождает курьёзную ситуацию.

Ну я же говорил - можно порешать, если сильно парит. Например - функция конструктор для элементов или еще чего. В любом случае - я точно не хочу иметь большой массив структур с мусором. В безопасном строгом языке. Если хочу - то пожалуйста в SYSTEM. Реальный пример сильно помог бы.

Легко такое сделать? Что нам об этом говорит опыт С++, Java, C#?

Опыт говорит, что функции в конце-концов бьются. Как раз потому, что в условиях множественного RETURN сопровождать большие функции - неприятно. Отсутствие множественного RETURN - только оттягивает конец :)

Вспомнил о ещё одной неудобности. В Обероне значение переменных можно менять, передавая их через параметры в процедуры. Легко представить ситуацию, когда такими процедурами можно также инциализировать, но при таком подходе получится это только с накладными расходами.

Опять же - поясните, что за накладные расходы такие. В каком месте.
« Последнее редактирование: Март 03, 2011, 11:53:19 pm от vlad »

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #52 : Март 09, 2011, 06:49:28 pm »
Нет ничего экстремального в инициализации по одному условию нескольких переменных и по смыслу не объединяемых в одну сущность.
Ну вот не знаю. В моем коде таких ситуаций (инициализация разных переменных по условию с последующим использованием этих переменных по другому условию) - не встречается. Хотите верьте - хотите нет. И я считаю такой код трудным для чтения - вместо плавного перетекания от одного к другому имеем рваные условия с возможностью запутаться - что, откуда и куда.[/quote]Обратите внимание, в цитируемом сообщении не было сказано про использование по разным условиям, поскольку в обсуждаемом вопросе важна лишь необходимость инициализации нескольких переменных по 1-му условию, не более.


Цитировать
Цитировать
Как, что? Для функций, возвращающих большие структуры, возникают большие накладные расходы на копирование. То же касается и массивов. Это можно обойти, но неизбежно вылезут другие шутки.
Не, не понимаю, о каком копировании речь? Код "X x = f();" всегда может быть автоматически сведен к "X x; f(x);". Если, конечно, не пытаться повторять плюсовую семантику с конструкторами копирования и т.д.
Потому я и написал, что можно обойти. А теперь про шутки, которые неизбежно вылезут.

struct S {int a,b};

s = S{s.b, s.a};//Прийдётся компилятор сделать шибко умным, чтобы правильно обрабатывать такие ситуации без ошибок и без накладных расходов

s = f(s);//А вот тут даже умный компилятор не знает как без накладных расходов не допустить ошибок в общем случае, прийдётся выдумывать другие хитрые механизмы.

S f(S s, int i) { return {s.b + 1, s.a / (i - 1)} }
S s = S{1, 2};//1
try {
  s = f(s, 1);//2
} catch {
    s = f(s, 2);//программист вправе ожидать, что до присваивания s всё ещё имеет 1-е значение.
}
Мне лениво писать ещё, просто пофантазируйте на эту тему. Например, когда параметр может оказаться частью возвращаемого значения и наоборот. Накладные расходы - это невинные шалости по сравнению с побочными эффектами подобного автоматического сведения.
Смотрю, Вы уже и в другую тему по этому поводу успели написать. Ничего, что-нибудь придумаете. Предупреждая ответ, что в случае VAR - параметров этих эффектов тоже не избежать, отвечу, что ...

Цитировать
Да, и всё-таки, как поможет функция-конструктор для большой структуры, если инициализировать всё-равно одной операцией?
Не, не понимаю в чем проблема...

Лень объяснять. Пусть проблемы не будет.

Цитировать
Цитировать
Нет, я имел ввиду ситуацию, когда нужно инициализировать именно в секции модуля, но мы знаем точно, что она там происходит, тем не менее везде нужно будет использовать проверку об инициализации.
Какая-то надуманная ситуация. Почему именно в секции модуля?
Потому что несколько переменных могут зависеть от общих временных данных.

Цитировать
Да никто ж не заставляет размазывать. Пропишите непосредственно перед секцией. Можно даже потребовать на уровне компилятора.
Как бы не так. Для того, чтобы проинициализировать осмысленным значением, бывает нужен более сложный алгоритм чем однострочник, и тут уж нужна процедура, объявленная до переменной, и, следовательно, появляется возможность размазывания. Но я не подумал в прошлый раз, что можно обойтись опережающим объявлением процедуры и минимизировать размазывание. Т.е. надо ввести возможность таких объявлений и в секции переменных.

Во первых, инициализация - это за исключением наиболее простых случаев, не забитие одним и тем же значеним всего массива. Ну а возможность в оригинальном Обероне объявить большой массив записей вместе с потенциальной необходимостью тут же инициализировать эти записи вообще порождает курьёзную ситуацию.

Цитировать
Ну я же говорил - можно порешать, если сильно парит. Например - функция конструктор для элементов или еще чего. В любом случае - я точно не хочу иметь большой массив структур с мусором. В безопасном строгом языке. Если хочу - то пожалуйста в SYSTEM. Реальный пример сильно помог бы.
Структуры и массивы - дело тонкое, а мусором является  любое не осмысленное значение, даже если оно прописано в присваивании, а иногда само присваивание становится мусором.
Цитировать
struct Stack {int count, int s[N]};
Stack s;
s.count = 0;
;
Структура инициализирована или нет?

Цитировать
Опыт говорит, что функции в конце-концов бьются. Как раз потому, что в условиях множественного RETURN сопровождать большие функции - неприятно. Отсутствие множественного RETURN - только оттягивает конец :)
В качестве шутки - сойдёт. Вы умеете переворачивать с ног на голову.

Вспомнил о ещё одной неудобности. В Обероне значение переменных можно менять, передавая их через параметры в процедуры. Легко представить ситуацию, когда такими процедурами можно также инциализировать, но при таком подходе получится это только с накладными расходами.

Опять же - поясните, что за накладные расходы такие. В каком месте.
[/quote]

f(a);//устанавливаем значение уже объявленной

T b = {...};//мусорное присваивание, оно же накладные расходы
f(b)// ах, да - просто не надо создавать такие процедуры( так может и VAR-параметры удалить; + ещё 1 изменение ), но я уже написал про ваш хитрый автоматический механизм, так что надо.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #53 : Март 09, 2011, 08:39:46 pm »
Обратите внимание, в цитируемом сообщении не было сказано про использование по разным условиям, поскольку в обсуждаемом вопросе важна лишь необходимость инициализации нескольких переменных по 1-му условию, не более.

Мне кажется, что в подобных случаях изначальная проблема в правильной декомпозиции. Пусть будет одно условие:

int a, b;
if (условие)
   a = ...
else
   b =...
/*общий код*/
if (условие)
   a;
else
   b;

Вот такая штука намного естественнее смотрится приведенная к такому виду:

int a, b;
if (условие)
   int a = ...
   f();/*общий код*/
   a;
else
   int b =...
   f();/*общий код*/
   b;

Цитировать
Цитировать
Если, конечно, не пытаться повторять плюсовую семантику с конструкторами копирования и т.д.
Потому я и написал, что можно обойти. А теперь про шутки, которые неизбежно вылезут.

struct S {int a,b};

s = S{s.b, s.a};//Прийдётся компилятор сделать шибко умным, чтобы правильно обрабатывать такие ситуации без ошибок и без накладных расходов

Хе-хе. А вот здесь мы имеем не инициализацию, а присваивание. Сильно разные вещи. Здесь всегда будет копирование. Оно здесь будет даже если вы напишите на оригинальном обероне по всем правилам - с объявлением временной структуры, ее инициализацией и последующим копированием.

Цитировать
s = f(s);//А вот тут даже умный компилятор не знает как без накладных расходов не допустить ошибок в общем случае, прийдётся выдумывать другие хитрые механизмы.

Аналогично. Это присваивание.

Цитировать
S f(S s, int i) { return {s.b + 1, s.a / (i - 1)} }
S s = S{1, 2};//1
try {
   s = f(s, 1);//2
} catch {
    s = f(s, 2);//программист вправе ожидать, что до присваивания s всё ещё имеет 1-е значение.
}

Аналогично. Это присваивание.

Цитировать
Цитировать
Какая-то надуманная ситуация. Почему именно в секции модуля?
Потому что несколько переменных могут зависеть от общих временных данных.

Ну и объявите эти временные данные здесь же, не в секции. В чем проблема-то?

Цитировать
Цитировать
Да никто ж не заставляет размазывать. Пропишите непосредственно перед секцией. Можно даже потребовать на уровне компилятора.
Как бы не так. Для того, чтобы проинициализировать осмысленным значением, бывает нужен более сложный алгоритм чем однострочник, и тут уж нужна процедура, объявленная до переменной, и, следовательно, появляется возможность размазывания.

Ну правильно. Все процедуры будут объявлены до переменной и до секции. Где размазывание? Тут на самом деле более интересная проблема: если инициализировать вызовом функции, то как обеспечить, чтобы функция не обратилась к этой же переменной модуля.

Структуры и массивы - дело тонкое, а мусором является  любое не осмысленное значение

Не, не скажите. С ноликами разница принципиальная. Если нолики всегда одинаковые, то и поведение всегда одинаковое (пусть даже и неправильное). А если мусор, то поведение начинает зависеть от фазы луны. Такое недопустимо в безопасном языке.

Цитировать
Цитировать
struct Stack {int count, int s[N]};
Stack s;
s.count = 0;
;
Структура инициализирована или нет?

Ошибка компиляции. Должна быть проинициализирована в точке объявления.

Цитировать
f(a);//устанавливаем значение уже объявленной

T b = {...};//мусорное присваивание, оно же накладные расходы
f(b)// ах, да - просто не надо создавать такие процедуры( так может и VAR-параметры удалить; + ещё 1 изменение ), но я уже написал про ваш хитрый автоматический механизм, так что надо.

Да, не надо писать такие процедуры. Если надо установить новое значение уже объявленной - пожалуйста, пишите a = f(). Да, в данном случае для a (объявление/инициализация/присваивание) накладные расходы при прочих равных будут больше, согласен. Зато есть гарантия, что структура не останется проинициализированной наполовину.
« Последнее редактирование: Март 09, 2011, 08:42:04 pm от vlad »

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #54 : Март 24, 2011, 05:50:22 pm »
Цитировать
Мне кажется, что в подобных случаях изначальная проблема в правильной декомпозиции.
int a, b;
if (условие)
   int a = ...
   f();/*общий код*/
   a;
else
   int b =...
   f();/*общий код*/
   b;
Пример немного странный, потому что либо а и б не используются в общем коде, либо они взаимозаменяемые переменные, что очень частный случай, либо в общем коде есть дополнительные проверки и его естественность теряется, либо общий код не такой уж и общий. А имел ввиду я что-то совсем банальное как, например
int a, b;
if условие
   a = ...
   b = ...
else
   a = ...
   b = ...
f(a, b);//общий код, не функция

Цитировать
Цитировать
Цитировать
Если, конечно, не пытаться повторять плюсовую семантику с конструкторами копирования и т.д.
Потому я и написал, что можно обойти. А теперь про шутки, которые неизбежно вылезут.
Цитировать
struct S {int a,b};
s = S{s.b, s.a};
Хе-хе. А вот здесь мы имеем не инициализацию, а присваивание. Сильно разные вещи. Здесь всегда будет копирование. Оно здесь будет даже если вы напишите на оригинальном обероне по всем правилам - с объявлением временной структуры, ее инициализацией и последующим копированием.
Цитировать
s = f(s);//А вот тут даже умный компилятор не знает как без накладных расходов не допустить ошибок в общем случае, прийдётся выдумывать другие хитрые механизмы.
Аналогично. Это присваивание.
Цитировать
S f(S s, int i) { return {s.b + 1, s.a / (i - 1)} }
S s = S{1, 2};//1
try {
  s = f(s, 1);//2
} catch {
    s = f(s, 2);//программист вправе ожидать, что до присваивания s всё ещё имеет 1-е значение.
}
Аналогично. Это присваивание.
Значит, я неправильно понял Вашу мысль. Думал, что Вы имели ввиду, что X x = f()-> X x;_f(x) будет всегда, в том числе и для повторного присваивания, а на самом деле будет так  X y;_f(y); x = y;
Да только это мало чего меняет в плане производительности, потому как кол-во повторных присваиваний может сильно превысить кол-во первых.
И понятно, что в приведённых примерах будет копирование в любом случае. Дело-то не в этом, а том, что при новой фишке, копирование и перерасход памяти должны выполняться вообще всегда при присваивании для простого компилятора без подвохов. А при явных механизмах программист сможет избежать этого там, где это нужно и возможно. Для циклов разница может быть большой.


Цитировать
Цитировать
Потому что несколько переменных могут зависеть от общих временных данных.
Ну и объявите эти временные данные здесь же, не в секции. В чем проблема-то?
В том, что временные переменные не должны делать вид, что они глобальные и занимать место там, где они не нужны.


Цитировать
бывает нужен более сложный алгоритм чем однострочник, и тут уж нужна процедура, объявленная до переменной, и, следовательно, появляется возможность размазывания.
Цитировать
Ну правильно. Все процедуры будут объявлены до переменной и до секции. Где размазывание? Тут на самом деле более интересная проблема: если инициализировать вызовом функции, то как обеспечить, чтобы функция не обратилась к этой же переменной модуля.
Я, конечно, имел ввиду более привычную схему. Конечно, можно всё перевернуть вверх дном, но как Вы сами заметили, это не решение, а только замена задачи.

Цитировать
Цитировать
struct Stack {int count, int s[N]};
Stack s;
s.count = 0;
;
Структура инициализирована или нет?
Ошибка компиляции. Должна быть проинициализирована в точке объявления.
Разумеется, вопрос не об этом, а о смысле.

Цитировать
Да, не надо писать такие процедуры. Если надо установить новое значение уже объявленной - пожалуйста, пишите a = f(). Да, в данном случае для a (объявление/инициализация/присваивание) накладные расходы при прочих равных будут больше, согласен. Зато есть гарантия, что структура не останется проинициализированной наполовину.
Иногда и бывает нужно проинициализировать наполовину, а то и практически на нуль, как со стэком или, например, при чтении из потока, к которому возвращаешься время от времени, да ещё при этом используешь прочитанную ранее часть структуры. И правильнее говорить не о гарантиях инициализации, а о гарантиях заполненности чем-то.

Или вот ещё пример
f(int a[][]) {
    for (int i = 0; i < len(a, 0); i++) {
      for (int k = 0; k < len(a, 1); k++) {
          a[k] = i + k;
      }
 }
}
И ещё раз спрошу, если скорость не важна, зачем вообще статические данные?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #55 : Март 24, 2011, 09:23:25 pm »
А имел ввиду я что-то совсем банальное как, например
int a, b;
if условие
   a = ...
   b = ...
else
   a = ...
   b = ...
f(a, b);//общий код, не функция

Не, ну здесь просто классический случай для туплы...

Цитировать
Да только это мало чего меняет в плане производительности, потому как кол-во повторных присваиваний может сильно превысить кол-во первых.

С чего вдруг? У меня в коде как раз минимум повторных присваиваний. Повторные присваивания возникают, как правило, при желании экономить временные переменные. Потому что после повторного присваивания переменная, скорее всего, будет иметь уже другой смысл. А желание такое возникает от отдельной секции VAR - поэтому такая секция есть зло :)

Цитировать
И понятно, что в приведённых примерах будет копирование в любом случае. Дело-то не в этом, а том, что при новой фишке, копирование и перерасход памяти должны выполняться вообще всегда при присваивании для простого компилятора без подвохов. А при явных механизмах программист сможет избежать этого там, где это нужно и возможно. Для циклов разница может быть большой.

Ну блин. В крайнем случае - напишите вторую функцию, которая будет принимать существующую структуру и переинициализировать ее. Делов-то. Закроете тот жалкий 1% случаев, когда это действительно надо. Вообще не понимаю откуда такая боязнь скопировать структуру, тем более на стеке. В C++ копируется направо и налево. Не помню ни одного раза, когда это приходилось бы оптимизировать (убирать лишние копирования).

Цитировать
Иногда и бывает нужно проинициализировать наполовину

Не бывает никогда. Принципиально. Или сама структура "неправильная" или это хэк уровня SYSTEM.

Цитировать
Или вот ещё пример
f(int a[][]) {
   for (int i = 0; i < len(a, 0); i++) {
      for (int k = 0; k < len(a, 1); k++) {
          a[k] = i + k;
      }
 }
}
И ещё раз спрошу, если скорость не важна, зачем вообще статические данные?

Ну да, массив, хитро инициализируется. Говорил же уже. Дайте реальный пример, когда "это" будет тормозить задачу.

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #56 : Март 25, 2011, 05:35:09 pm »
Не, ну здесь просто классический случай для туплы...
Из-за задержки с моим предыдущим ответом Вы, похоже, выпали из контекста. Иначе сложно объяснить, почему Вы, будто бы возражая, сами написали то, к чему я и вёл.
Цитировать
С чего вдруг? У меня в коде как раз минимум повторных присваиваний. Повторные присваивания возникают, как правило, при желании экономить временные переменные. Потому что после повторного присваивания переменная, скорее всего, будет иметь уже другой смысл. А желание такое возникает от отдельной секции VAR - поэтому такая секция есть зло :)
С того, что повторные присваивания возникают в основном в циклах и некоторых других алгоритмах, а не из-за секции VAR (за собой такого не припомню). Но Вы-то циклов не пишите.

Цитировать
Ну блин. В крайнем случае - напишите вторую функцию, которая будет принимать существующую структуру и переинициализировать ее. Делов-то. Закроете тот жалкий 1% случаев, когда это действительно надо. Вообще не понимаю откуда такая боязнь скопировать структуру, тем более на стеке. В C++ копируется направо и налево. Не помню ни одного раза, когда это приходилось бы оптимизировать (убирать лишние копирования).
Это чень удобно иметь по 2-а экземпляра почти одинаковых функций, что особо актуально для функций, доступных только в исполняемых кодах. Хорошо хоть, что это жалкий % случаев.
Цитировать
Ну да, массив, хитро инициализируется. Говорил же уже. Дайте реальный пример, когда "это" будет тормозить задачу.
Тут я больше хотел обратить внимание на то, что часть массива (длины его измерений) используются до того, как инициализируется его тело. Подобное можно отнести и к некоторым структурам, но как мы уже абсолютно точно выяснили, это всего лишь грязный хак уровня SYSTEM.

Ваша просьба предоставить реальный пример, где вылезали бы проблемы с производительностью не более чем провокация на бессмысленные действия :) , поскольку ответ на самый крайний случай был уже озвучен.
Цитировать
напишите вторую функцию, которая будет принимать существующую структуру(массив) и переинициализировать ее. Делов-то. Закроете тот жалкий 1% случаев, когда это действительно надо.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #57 : Март 25, 2011, 06:33:16 pm »
Цитировать
С чего вдруг? У меня в коде как раз минимум повторных присваиваний. Повторные присваивания возникают, как правило, при желании экономить временные переменные. Потому что после повторного присваивания переменная, скорее всего, будет иметь уже другой смысл. А желание такое возникает от отдельной секции VAR - поэтому такая секция есть зло :)
С того, что повторные присваивания возникают в основном в циклах и некоторых других алгоритмах, а не из-за секции VAR (за собой такого не припомню). Но Вы-то циклов не пишите.

В циклах - это будут локальные переменные цикла. При этом, как мы выяснили, даже в случае структур никаких проблем с производительностью не будет. Если же речь идет о внешней (по отношению к циклу) переменной-структуре, то мне очень трудно представить пример, когда на каждом шаге цикла надо будет ее присваивать новому значению.

Цитировать
Ваша просьба предоставить реальный пример, где вылезали бы проблемы с производительностью не более чем провокация на бессмысленные действия :)

Это не провокация. Это желание показать, что это не настолько принципиальная проблема. Да, я признаю, что такой подход не всегда будет удобен и конечно у него есть свои недостатки. Но я говорю о том, что он менее "проблемный" (по моему мнению), чем существующий сейчас в обероне (отдельная секция VAR, неинициализированные переменные).

Илья Ермаков

  • Full Member
  • ***
  • Сообщений: 177
    • Просмотр профиля
    • OberonCore
Re:Приспособим PureBuilder для разработки игр
« Ответ #58 : Март 26, 2011, 09:33:19 pm »
В циклах - это будут локальные переменные цикла. При этом, как мы выяснили, даже в случае структур никаких проблем с производительностью не будет. Если же речь идет о внешней (по отношению к циклу) переменной-структуре, то мне очень трудно представить пример, когда на каждом шаге цикла надо будет ее присваивать новому значению.

Фактически, нормальный цикл, в общем виде - это:
--код, задающий вектору варьируемых в цикле параметров начальное состояние--
ПОКА вектор не сошёлся к целевому множеству состояний ДЕЛАТЬ
  -- итерация над вектором параметров --
КОН;
-- код, употребляющий конечное состояние параметров цикла--

Как Вы так собрались изолировать параметры цикла от кода до и после? Вводить синтаксические секции для кода до и кода после? Допустим.
Но мне кажется, что Вы вообще держите в голове случай с for и break внутри, и именно около break пересовываете эти значения из локальных переменных цикла во вне. Если так, то брррр.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #59 : Март 28, 2011, 07:47:42 pm »
Как Вы так собрались изолировать параметры цикла от кода до и после? Вводить синтаксические секции для кода до и кода после? Допустим.
Но мне кажется, что Вы вообще держите в голове случай с for и break внутри, и именно около break пересовываете эти значения из локальных переменных цикла во вне. Если так, то брррр.

Да, тут ваши "привильные" циклы с дублированием кода для первого шага и последующих - будут плохо работать :)
i := same_code;
WHILE ...i...
...
i := same_code
...

Ну извините :) Тем хуже для правильных циклов :)