Oberon space

General Category => Общий раздел => Тема начата: vlad от Февраль 17, 2011, 03:43:16 am

Название: Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 03:43:16 am
Цитата: Сергей Прохоренко
Уже полгода на моем рабочем столе лежит презентация The Next Mainstream Programming Language: A Game Developer’s Perspective (http://www.google.ru/url?sa=t&source=web&cd=1&sqi=2&ved=0CBcQFjAA&url=http%3A%2F%2Fwww.cs.princeton.edu%2F~dpw%2Fpopl%2F06%2FTim-POPL.ppt&rct=j&q=%22Game%20Development%3A%20Gears%20of%20War%22&ei=kN1aTYuNPMqBOpLjvZ0L&usg=AFQjCNH1lYwuSG7QJy3ShTC6uRB2biG-ag&sig2=zxt4pID-HdB083eGOMEO2w&cad=rja) - крик души разработчика игр. Лежит как напоминание о том, что хороший структурный редактор должен соответствовать этим ясно выраженным потребностям. Должен признать, что предложенные автором решения мне понравились. А компьютерные игры - это передовой край Computer Science, эталон пригодности инструментального программного обеспечения к решению сложных задач.

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

По поводу нулевых указателей и неинициализированных переменных. Я уже выступал на оригинальном форуме (http://forum.oberoncore.ru (http://forum.oberoncore.ru)) и наверняка есть ЯП в которых эта проблема в каком то виде решена, но если подытожить применительно к оберону и структурному редактору, то основные тезисы такие:
- Неинициализированных переменных нет, потому что объявление переменной совмещено с ее инициализацией синтаксически. A-ля VAR i: INTEGER := 3.
- Указатели по умолчанию ненулевые (обязаны быть проинициализированы реальным объектом или другим ненулевым указателем).
- Можно объявить нулевой указатель. Это другой тип, совместимый с ненулевым указателем в одну сторону: ненулевой указатель может быть приведен к нулевому, но не наоборот. Нулевой указатель не может быть разыменован.
- Для получения ненулевого указателя из нулевого есть специальная синтаксическая конструкция вроде обероновской проверки/приведения типа с помощью WITH. Если проверка сработала, то выполняется ветка кода, где "виден" ненулевой указатель.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Geniepro от Февраль 17, 2011, 06:29:47 am
В том моём сообщении, исковерканном Темиргалеевым (да ещё и с оскорбительной уничижительной пометкой "экспертное" -- именно в кавычках) я по пунктам ответил Сергею Прохоренко, что фактически ничего этого в КП/ББ нет, даже сборщик мусора -- и тот не реалтаймный (GC, замораживающий мир, в интерактивных играх типа Unreal неприемлем).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 07:34:27 am
Я вообще говоря долго думал о эффективном и при этом безопасном языке. Безопасный -- я имею ввиду проверка на ошибки на этапе компиляции. Эффективный -- проверка ИСКЛЮЧИТЕЛЬНО на этапе компиляции.

В частности проверка численных переполнений и выход за границы массива.

Таки вот, я пришел к выводу, что сделать подобное для тьюринг-полного языка невозможно (я это даже помнится доказал). Следовательно нужно попробовать построить тьюринг-не полный подъязык. Кроме того, мне интуитивно кажется, что процентов 90 всего кода в современных приложениях может быть писано на таком вот подъязыке. Я пробовал на наколеночном прототипе написать quicksort -- получилось. И оно даже внятней смотрелось, чем вариант даденый Виртом в своей книжке.

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

Вот как-то так.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 07:38:33 am
Т.е. программа должна получаться верна по построению. Не должно быть зацикливаний, выходов за границы, численных переполнений.

Естественно ошибки алгоритмов (хотели сделать одно, а сделали таки другое) останутся, т.е. когда реализовали по сути другой алгоритм.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 07:52:08 am
Кстати, если мне память не изменяет, то языки с зависимыми типами, вроде Agda и т.п., где как раз на этапе компиляции проверяется всё от и до, не являются тьюринг полными (точнее то их подмножество где всё это как раз проверяется и доказывается). Правда они таки функциональные, я мне хочется тут императивный. Ну и хочется без столь страшной доказательной математике (я не верю что масс-программист её осилит, собственно даже хаскеля народ боится).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Peter Almazov от Февраль 17, 2011, 08:13:31 am
Я пробовал на наколеночном прототипе написать quicksort -- получилось.
И как оно выглядит?
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 08:17:45 am
Я в конфу кидал исходник. Но тогда вроде бы логи не велись ещё, поэтому оно пока кануло в лету. :-)
Постараюсь на выходных восстановить.

Там небыло while'ов. Там небыло произвольного доступа к индексам массивов. Циклы шли четко по множествам индексов, на каждой итерации цикла выкидывался из множества индексов как минимум один индекс (можно выкинуть больше). Добавить во множество индексов ничего нельзя. Из цикла можно преждевременно выйти (break), потому как этот выход на безопасность алгоритма никак не влияет (с т.з. выходов за границы, целочисленного переполнения и т.п.).

У меня проблемы случились позже, после qsort'a -- я попытался построить алгоритм с экспоненциальной сложностью, и у меня с ходу не получилось это вменяемо сделать. Надо думать дальше.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Geniepro от Февраль 17, 2011, 08:45:14 am
Надо бы выделить эти размышления о таком безопасном языке в отдельную тему...

Проверки на отсутствие зацикливаний -- это уже из области тотального ФП -- там все функции заведомо завершаемые, то есть полностью вычислимые.
А для работы с бесконечными циклами -- а такие тоже иногда нужны -- корекурсия, то есть типа кофункции.
Всё никак не могу заставить себя перевести статью Дэвида Тёрнера про тотальное ФП. Надо сделать -- небольшая она...
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 09:27:52 am
Ну, мой тезис таков, что это может быть не ФП, а вполне себе ИП, но не тьюринг полное просто. Т.е. это ортогонально ФП и ИП. Кстати, такой мелкий и убогий язычок очень пригодился бы для, например, написания nif'ов в ерланге (где важна как раз надежность, скорость и гарантированное завершение за определеный квант времени).

Кроме всего прочего, я думаю, что алгоритмы на таковом языке можно будет довольно просто (и даже автоматически) проверять на сложность. И уже при компиляции можно будет примерно оценить сколько при каких входных данных оно сожрет памяти и процессорного времени.

Почему я говорю именно про ИЯ? Потому, что для не тьюринг-полного языка не нужна иммутабельность. По кр. мере тотальная иммутабельность. В общем, тут можно и нужно много о чем ещё подумать, поэкспериментировать. Любые коментарии мысли (даже в порядке полного бреда) приветствуются.

PS. И да, именно вот это то и нужно для игр по сути.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Galkov от Февраль 17, 2011, 10:43:58 am
Потому, что для не тьюринг-полного языка не нужна иммутабельность. По кр. мере тотальная иммутабельность.
Хм...
Вот помню цитату из Лебедя (сам слышал): "у нас в армии на такое говорили - не делайте умное лицо, ведь Вы же Офицер!!!"

В смысле - разжуйте по буквам эту цитату. Честное слово, я быстро учусь  :D


А, да... ВСЕМ ПРИВЕТ !!!

Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 10:52:12 am
Т.е. в отличае от современного ФП, где грубо говоря нет присваиваний вообще и нет изменения значений чего-либо, в императивном не тьюринг полном языке, я думаю что можно будет разрешить некоторые типы изменений по крайней мере локальных переменных.

Ну, например та же сортировка массива -- сортировка будет вестись без дополнительного выделения памяти, т.е. прямо в самом массиве. В отличае от ФП, где придется плодить копии массивов, ведь там данные иммутабельны, и изменять тот же массив мы не имеем права (да, я знаю про монаду IO и монаду ST, но это таки отступление некоторое от канонов, и они таки дают меньшую надежность чем таковой не тьюринг-полный императивный язык).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Geniepro от Февраль 17, 2011, 11:35:26 am
Всё же мне кажется, что можно сделать вполне внутри настоящий чистый и тотальный язык, но замаскировать его таким синтаксисом, что будет похоже на ИЯ, но с такими ограничениями, которые дадут ему безопасность.
Под маскировкой я имею в виду, например, библиотеку Language.Basic (http://hackage.haskell.org/packages/archive/BASIC/latest/doc/html/Language-BASIC.html) в Хаскелле, позволяющую писать на Хаскелле такие во программы:
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
{-# LANGUAGE ExtendedDefaultRules, OverloadedStrings #-}
module HiLo where
import Language.BASIC

main :: IO ()
main = runBASIC $ do
    10 GOSUB 1000
    20 PRINT "* Welcome to HiLo *"
    30 GOSUB 1000

    100 LET I := INT(100 * RND(X))
--    110 PRINT I
    200 PRINT "Guess my number:"
    210 INPUT X
    220 LET S := SGN(I-X)
    230 IF S <> 0 THEN 300

    240 FOR X := 1 TO 5
    250  PRINT X*X;" You won!"
    260 NEXT X
    270 STOP

    300 IF S <> 1 THEN 400
    310 PRINT "Your guess ";X;" is too low."
    320 GOTO 200

    400 PRINT "Your guess ";X;" is too high."
    410 GOTO 200

    1000 PRINT "*******************"
    1010 RETURN

    9999 END
http://augustss.blogspot.com/2009/02/regression-they-say-that-as-you-get.html
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 11:45:25 am
Да, я тоже полагаю что на хаскеле можно сделать такой EDSL и с типизацией там будет всё хорошо. Хаскель тем и хорош, что там можно обкатывать новые парадигмы :-) Собственно для того он и делался, делается и будет делаться.

Но в последствии неплохо бы иметь отдельный компилятор для такого язычка. Потому как ghc это явный оверкил :-)

Но вначале надо поэкспериментировать/подумать как он вообще должен выглядеть.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 12:59:53 pm
Т.е. программа должна получаться верна по построению. Не должно быть зацикливаний, выходов за границы, численных переполнений.

А чем, собственно, зацикливание отличается от просто очень долгого алгоритма? С точки зрения конечного результата в виде "зависания".
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Geniepro от Февраль 17, 2011, 01:03:58 pm
А чем, собственно, зацикливание отличается от просто очень долгого алгоритма? С точки зрения конечного результата в виде "зависания".
Ну, очень долгий алгоритм в конце концов всё же завершится с каким-то результатом, а зацикливание типа "10 GOTO 10" не завершится никогда.
При определённом подходе к программированию (например тотальное ФП) можно получить гарантию того, что алгоритм рано или поздно завершится, а иначе программа просто не скомпилируется из-за ошибки типизации.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 01:11:51 pm
Т.е. программа должна получаться верна по построению. Не должно быть зацикливаний, выходов за границы, численных переполнений.

А чем, собственно, зацикливание отличается от просто очень долгого алгоритма? С точки зрения конечного результата в виде "зависания".
Тут есть отличие -- знаем мы что оно зациклилось, или не знаем. Если знаем, тогда ждать смысла не имеет, надо убить (если зациклилось), если мы гарантировано знаем что алгоритм конечный, то можем подождать. Более того, можем как-то проследить процесс исполнения и что-то спрогнозировать. Т.е. процесс получаем управляемый.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 01:16:20 pm
Тут есть отличие -- знаем мы что оно зациклилось, или не знаем. Если знаем, тогда ждать смысла не имеет, надо убить (если зациклилось), если мы гарантировано знаем что алгоритм конечный, то можем подождать. Более того, можем как-то проследить процесс исполнения и что-то спрогнозировать. Т.е. процесс получаем управляемый.

С точки зрения пользователя программы все равно - зависла она на совсем или сделает свою работу через пару миллиардов лет. И так и так - глючит :)

P.S. Хотя, конечно, иметь гарантии завершимости на этапе компиляции было бы полезно. Сколько-то ошибок/опечаток не пролезло бы.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Сергей Прохоренко от Февраль 17, 2011, 01:20:14 pm
По поводу нулевых указателей и неинициализированных переменных. Я уже выступал на оригинальном форуме (http://forum.oberoncore.ru (http://forum.oberoncore.ru)) и наверняка есть ЯП в которых эта проблема в каком то виде решена, но если подытожить применительно к оберону и структурному редактору, то основные тезисы такие:
- Неинициализированных переменных нет, потому что объявление переменной совмещено с ее инициализацией синтаксически. A-ля VAR i: INTEGER := 3.
- Указатели по умолчанию ненулевые (обязаны быть проинициализированы реальным объектом или другим ненулевым указателем).
- Можно объявить нулевой указатель. Это другой тип, совместимый с ненулевым указателем в одну сторону: ненулевой указатель может быть приведен к нулевому, но не наоборот. Нулевой указатель не может быть разыменован.
- Для получения ненулевого указателя из нулевого есть специальная синтаксическая конструкция вроде обероновской проверки/приведения типа с помощью WITH. Если проверка сработала, то выполняется ветка кода, где "виден" ненулевой указатель.

Я против такой имитации решения проблемы.  :-\\

Это похоже на то, как действуют пользователи MS Access. Там есть поля, которые программист делает обязательными для заполнения. Хитро...умные пользователи ставят пробел, и программа считает, что всё OK. Ну и кому от этого польза? Реальная-то информация не введена, а введена галиматья!

Вместо того, чтобы напрячь разработчика компилятора, мы, получается, заставляем прикладного программиста вводить бессмысленные значения, чтобы только компилятор не ругался! На самом деле компилятор должен найти те переменные, которые заведомо никогда не инициализируются. Если же в процессе исполнения программы до инициализации просто не дойдет дело, то тогда должно генерироваться исключение.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 01:42:47 pm
Вообще, скажем в яве, является распространенной практикой не использовать нулевые указатели вообще.

Делается это так (допустим у нас есть метод который должен возвращать найденую строку, иногда он строку не находит, и что в этом случае делать? а вот что):
class SomeClass {
    static nullString = "SomeClass null string";

    String findString(int id) {
        if (canFind(id)) // получилось найти
            return foundString; // возвращаем найденую строку
        else
            return nullString;
    }
}
Т.о. нуль оно не возвращает никогда. Всегда возвращается некое осмысленное значение. Это не панацения конечно, но это сильно помогает отладке и диагностике ошибок. Работа программы становится вроде как более предстказуемой с случае ошибки.

К сожалению Ява, в отличае от например Ады, не позволяет определить тип ненулевой ссылки. А тут бы оно было бы очень полезно. Поэтому среди Адовцев Ява считается языком маленьким и слабеньким :-)
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 01:45:40 pm
Я против такой имитации решения проблемы.  :-\\

Это похоже на то, как действуют пользователи MS Access. Там есть поля, которые программист делает обязательными для заполнения. Хитро...умные пользователи ставят пробел, и программа считает, что всё OK. Ну и кому от этого польза? Реальная-то информация не введена, а введена галиматья!

Нет. Язык дает средство сделать код надежнее/понятнее/эффективнее. Если программист не хочет этим воспользоваться - то тут языком дело не исправишь. Ключевое отличие от Access в том, что там есть разделение на программиста, который думает, что поле обязательно и требует ввести туда значение, и пользователя, который знает, что на самом деле оно не обязательно и вбивает туда мусор :) В случае ЯП такого разделения нет. Программу пишет программист и он же вбивает осмысленное значение, чтобы яснее выразить свою мысль. Для читающего программиста инициализация делает код понятнее.

Вместо того, чтобы напрячь разработчика компилятора, мы, получается, заставляем прикладного программиста вводить бессмысленные значения, чтобы только компилятор не ругался! На самом деле компилятор должен найти те переменные, которые заведомо никогда не инициализируются. Если же в процессе исполнения программы до инициализации просто не дойдет дело, то тогда должно генерироваться исключение.

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

P.S. Еще хочу сказать, что такой подход (тотальная инициализация и ненулевые указатели) уже несколько лет успешно обкатан мной лично на практике. Реально "ненужных" присваиваний (нулевых) чрезвычайно мало - они возникают у меня только на стыке с Win API, когда какая-то переменная будет заведомо проинициализирована вызовом функции, но я ее все равно инициализирую в 0, чтобы не нарушать стиль. Проблема только в том, что в случае С++ это вопрос стиля - компилятор позволяет так писать, но не требует.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 01:50:30 pm
К сожалению Ява, в отличае от например Ады, не позволяет определить тип ненулевой ссылки. А тут бы оно было бы очень полезно. Поэтому среди Адовцев Ява считается языком маленьким и слабеньким :-)

Угу. Глядя на жабовский/обероновский код, в который пришел указатель, никогда не сможешь сказать, что здесь никогда не будет "null dereference exception". Потому что нет _типа_ ненулевых указателей.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 02:12:42 pm
Цитата: Сергей Прохоренко
Мы говорим о разных вещах. Длинных типов обычно даже слишком много разных, что ведет к несовместимости по типу. Поэтому, например, Вирт все их просто отбросил в Обероне-07. Ему это было сделать просто - он ведь не разрабатывает игры - ему и не нужны длинные типы.

У этих библиотечных типов есть еще один порок - программисту легко ошибиться в своих запросах. Слишком короткие типы приведут к переполнению, а слишком длинные сожрут место в памяти и на диске и замедлят обработку данных.

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

У меня очень сильные сомнения, что эти проблемы решены хоть в каком-то языке программирования, включая КП.
Собственно я говорил именно об этом. Именно эти числа, о которых вы говорите есть сразу в Haskell и Erlang'e. Функция подсчета факториала от 5ти будет одинаково использоваться и для подсчета от 10000. В первом случае будет использован int32, во втором случае, начиная с некоторого шага, будет использовано длинное целое (переменной длины). При этом тип останется тот же -- Integer.

Цитата: Сергей Прохоренко
Поэтому я призываю всех подумать, как реально их можно решить. Полный отказ от указателей или какой-то другой абсолютно необходимой функциональности, требование к программисту всё инициализировать при объявлении каким-нибудь мусором, попытка всё спихнуть на обработку исключения - не считаются решением проблемы.
Ну, я собственно уже предложил :-)
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Сергей Прохоренко от Февраль 17, 2011, 02:35:03 pm
Я думаю, что нужно предоставить программисту удобную возможность проинициализировать переменную при объявлении и напомнить ему, если это не сделано. Но принуждать к инициализации не нужно. Иначе в рантайме уже не удастся сгенерировать и обработать исключение, когда действительно осмысленная инициализация не прошла. Программа будет утверждать, что "всё хорошо, прекрасная маркиза", хотя на самом деле это не так.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 02:39:44 pm
Я думаю, что нужно предоставить программисту удобную возможность проинициализировать переменную при объявлении и напомнить ему, если это не сделано. Но принуждать к инициализации не нужно. Иначе в рантайме уже не удастся сгенерировать и обработать исключение, когда действительно осмысленная инициализация не прошла. Программа будет утверждать, что "всё хорошо, прекрасная маркиза", хотя на самом деле это не так.

Давайте зайдем от обратного :) Придумайте пример, когда вы не можете осмысленно инициализировать переменную сразу. Мы над ним помедитируем :) Рассмотрим достоинства и недостатки.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Февраль 17, 2011, 04:37:44 pm
...

Type t1, t2;

if (c1) {
    t1 = f1(p1);
  t2 = f2(p2);
} else {
    t1 = f3(p3);
}

...

if (c1 && c2) {
 f5(t1);
   f6(t2);
} else {
 f7(t1);
}
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 05:53:42 pm
...

Type t1, t2;

if (c1) {
    t1 = f1(p1);
  t2 = f2(p2);
} else {
    t1 = f3(p3);
}

...

if (c1 && c2) {
 f5(t1);
   f6(t2);
} else {
 f7(t1);
}

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

Type t1 = с1 ? f1(p1) : f3(p3);

...

if (c1 && c2) {
   f5(t1);
        Type t2 = f2(p2);
        f6(t2);
} else {
 f7(t1);
}
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Февраль 17, 2011, 06:39:43 pm
В предыдущий раз недостаточно точно выразил мысль, поскольку f1..f7, это на деле не неделимые функции. Так будет точнее
Type t1, t2;

if (c1) {
   Type t3 = f0(p1, p2);
   t1 = f1(p1, t3);
   t2 = f2(p2, t3);
} else {
   t1 = f3(p3);
}

...

if (c1 && c2) {
   f5(t1);
   f6(t2);
} else {
   f7(t1);
}
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 17, 2011, 07:40:29 pm
В предыдущий раз недостаточно точно выразил мысль, поскольку f1..f7, это на деле не неделимые функции. Так будет точнее
Type t1, t2;

if (c1) {
   Type t3 = f0(p1, p2);    
   t1 = f1(p1, t3);
   t2 = f2(p2, t3);
} else {
   t1 = f3(p3);
}

...

if (c1 && c2) {
   f5(t1);
   f6(t2);
} else {
   f7(t1);
}

Да, это интереснее :) Первый кусок кода:
if (c1) {
   Type t3 = f0(p1, p2);  
   t1 = f1(p1, t3);
   t2 = f2(p2, t3);
} else {
   t1 = f3(p3);
}

выносим в функцию, которая возвращает t1 и "опциональное" t2. Тогда оставшийся кусок будет выглядеть так:

(Type t1, TypeOptional t2) = f();
...
if (t2.initialized() && c2) {
   f5(t1);
   f6(t2); // здесь t2 гарантировано не "пустое", компилятор про это знает, потому что выше произошла проверка/приведение типа от TypeOptional к Type
} else {
   f7(t1);
}
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Валерий Лаптев от Февраль 17, 2011, 08:12:06 pm
Собственно я говорил именно об этом. Именно эти числа, о которых вы говорите есть сразу в Haskell и Erlang'e. Функция подсчета факториала от 5ти будет одинаково использоваться и для подсчета от 10000. В первом случае будет использован int32, во втором случае, начиная с некоторого шага, будет использовано длинное целое (переменной длины). При этом тип останется тот же -- Integer.
Мы в семантическом редакторе реализуем учебный язык без привязки к размерам встроенных типов. Я поначалу хотел даже отказаться от деления на целые и дробные, и оставить один тип Число. Но мне показалось, что это слишком радикально - все же во всех языках числа не менее двух типов.   
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 17, 2011, 08:16:28 pm
Собственно я говорил именно об этом. Именно эти числа, о которых вы говорите есть сразу в Haskell и Erlang'e. Функция подсчета факториала от 5ти будет одинаково использоваться и для подсчета от 10000. В первом случае будет использован int32, во втором случае, начиная с некоторого шага, будет использовано длинное целое (переменной длины). При этом тип останется тот же -- Integer.
Мы в семантическом редакторе реализуем учебный язык без привязки к размерам встроенных типов. Я поначалу хотел даже отказаться от деления на целые и дробные, и оставить один тип Число. Но мне показалось, что это слишком радикально - все же во всех языках числа не менее двух типов.   
Во многих языках тяготяющик к скриптовому применению, есть только просто число. Например в той же Lua. И мне кажется, что даже в js это так, но тут могу ошибаться.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Berserker от Февраль 17, 2011, 08:30:49 pm
Javascript - Number.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Февраль 20, 2011, 11:38:28 am
Да, это интереснее :) ...
Напишите, пожалуйста, весь код. А заодно опишите, какими свойствами должен обладать язык, чтобы делать такие штуки было удобно. И как Вы считаете, можно ли считать это правило маленькой добавкой в язык уровня Оберон (когда-то Вы писали, что оно легко и элегантно впишется в его гипотетический диалект).

Также подумайте, чего этот способ делает больше: решения проблем или их создания (просто подумайте, отвечать не надо, поскольку Ваш ответ и так очевиден с вероятностью 87.34%).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 21, 2011, 03:01:03 pm
Напишите, пожалуйста, весь код.

C расчетом, что у нас в языке а-ля оберон с сишным синтаксисом есть туплы (если нет, то всегда можно отбиться структурами/записями):
(Type t1, TypeOptional t2)
f() {
    if (c1) {
        Type t3 = f0(p1, p2);    
         return f1(p1, t3), f2(p2, t3);
    } else {
        return t1, null;
    }
}
...

Type t1, TypeOptional t2 = f();
...
if (optional_cast<Type>(t2) && c2) {
   f5(t1);
   f6(t2); // здесь t2 гарантировано не "пустое", компилятор про это знает, потому что выше произошла проверка/приведение типа от TypeOptional к Type
} else {
   f7(t1);
}

Цитата: Comdiv
А заодно опишите, какими свойствами должен обладать язык, чтобы делать такие штуки было удобно. И как Вы считаете, можно ли считать это правило маленькой добавкой в язык уровня Оберон (когда-то Вы писали, что оно легко и элегантно впишется в его гипотетический диалект).

Если в порядке "величины" добавки, то от языка нужны следующие свойства:
1. Механизм исключений в каком-то виде. Если инициализировать при объявлении, то код ошибки обрабатывать уже негде. Да, это совсем немаленькая добавка, но зато хорошо изученная и без нее жить трудно безотносительно к предлагаемым изменениям.
2. Объявление локальных переменных по месту (упразднение отдельной секции VAR). Тоже повсеместно доказанное благо, хотя убежденные паскалисты держатся за нее до конца :)
3. Добавление null'able в систему типов. Существующих примеров много, начиная с SQL и заканчивая C#, ничего нового, все известно и понятно.
4. Тернарный оператор и туплы. Можно и без них (особенно без туплов), но с ними приятнее :)

Цитата: Comdiv
Также подумайте, чего этот способ делает больше: решения проблем или их создания (просто подумайте, отвечать не надо, поскольку Ваш ответ и так очевиден с вероятностью 87.34%).

Я пока не нашел каких-то проблем/противоречий, к которым могут привести предлагаемые изменения. Изменений в компиляторе относительно немного. Язык станет более выразительным (за счет расширения системы типов) и сменится стиль написания кода в сторону более гранулярной декомпозиции (как в данном примере).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 21, 2011, 03:15:55 pm
Поправил оформление цитат в сообщении vlad'a. (добавил закрывающий тэг [/quote]).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Февраль 22, 2011, 06:50:42 pm
C расчетом, что у нас в языке а-ля оберон с сишным синтаксисом есть туплы (если нет, то всегда можно отбиться структурами/записями):
С учётом того, что это должно быть удобным (иначе кто так будет писать?), то либо кортежи обязательны, либо структуры должны быть существенно переработаны.
Я просил привести весь код, но создаётся впечатление, что многое всё же недосказано. Что такое TypeOptional - фишка языка, позволяющая прилепливать к типу слово Optional, после чего получаем особый тип? Или он всё же где-то объявлен, тогда где его код?

1. Механизм исключений в каком-то виде. Если инициализировать при объявлении, то код ошибки обрабатывать уже негде. Да, это совсем немаленькая добавка, но зато хорошо изученная и без нее жить трудно безотносительно к предлагаемым изменениям.
2. Объявление локальных переменных по месту (упразднение отдельной секции VAR). Тоже повсеместно доказанное благо, хотя убежденные паскалисты держатся за нее до конца :)
3. Добавление null'able в систему типов. Существующих примеров много, начиная с SQL и заканчивая C#, ничего нового, все известно и понятно.
4. Тернарный оператор и туплы. Можно и без них (особенно без туплов), но с ними приятнее :)

Лихо Вы объединили тернарный оператор и кортежи в один пункт, полагаю, что 2-е намного сложнее 1-го. Также думаю, что без них нельзя, иначе фишка будет не удобной.

Полагаю, что кое-что забыто (я не прогонял это тщательно в уме):
Отказ от статических структур и от структур как таковых, одни объекты, либо добавление хитрых механизмов для работы с ними.
Добавление конструкторов, да не простых, а с инициализацией всех данных объекта.
Объявление данных модуля с инициализацией.
Отказ от данных модуля, которые  не могут быть инициализированы по месту.
Как-то придумать инциализацию по месту массивов, или отказ от них.
Отказ от 1-го RETURN (Оберон ведь движется в этом направлении)
В Вашем примере, не шаблоны ли использованы для приведения типа?
Возможно, что-то ещё.

Про исключения не понял, почему нельзя возвращать код ошибки вместе с результатом?

По-моему вырисовывается не диалект Оберона, а совсем другой язык.

Цитата: Comdiv
Также подумайте, чего этот способ делает больше: решения проблем или их создания (просто подумайте, отвечать не надо, поскольку Ваш ответ и так очевиден с вероятностью 87.34%).

Я пока не нашел каких-то проблем/противоречий, к которым могут привести предлагаемые изменения. Изменений в компиляторе относительно немного.
Предложу свои варианты ответов:
1.При необходимости многие будут не выкручиваться в эквивалентные преобразование кода, а инициализировать по месту мусорно, что затруднит обнаружение ошибки, в случае если переменная так и не будет проинициализирована нормально (за что боролись, на то и напоролись).
2.Усложнение языка и компилятора, ради небольшой проблемы. Ведь изначально шла речь о простом изменении, существенно более простом, чем то, что реализовано в анализаторе BlackBox или компиляторе java. А если нам нужен другой язык, с кортежами, исключениями, nullable типами и другими фишками, это другой вопрос.
3.Возможно, что-то ещё. Мне не так-то просто предвидеть все последствия от необходимых изменений.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 22, 2011, 07:28:56 pm
С учётом того, что это должно быть удобным (иначе кто так будет писать?), то либо кортежи обязательны, либо структуры должны быть существенно переработаны.

С рекордами можно жить (я в С++ живу, хотя там есть boost::tuple). Писанины чуть больше, зато поля именованы, зачастую это повышает читабельность. Существенной переработки применительно к оберону не надо, достаточно иметь синтаксис для инициализации рекордов (так же как и массивов). Этот недостающий сахар уже обсуждали - без него неудобно и в классическом обероне.

Цитата: Comdiv
Я просил привести весь код, но создаётся впечатление, что многое всё же недосказано.

Ну трудно писать на гипотетическом языке, если что-то непонятно - проще пояснить словами.

Цитата: Comdiv
Что такое TypeOptional - фишка языка, позволяющая прилепливать к типу слово Optional, после чего получаем особый тип? Или он всё же где-то объявлен, тогда где его код?

Это что-то типа:
TYPE TypeOptional = OPTIONAL INTEGER;
или
typedef optional int TypeOptional;

Цитата: Comdiv
Лихо Вы объединили тернарный оператор и кортежи в один пункт,

Оно не принципиально :) Хотя тернарный оператор все же нужнее.

Цитата: Comdiv
полагаю, что 2-е намного сложнее 1-го. Также думаю, что без них нельзя, иначе фишка будет не удобной.

Чего ж там сложного??? Компилятор уже умеет иметь дело с временными переменными (для вычисления выражений). Объявление по месту - такая же временная переменная.

Цитата: Comdiv
Полагаю, что кое-что забыто (я не прогонял это тщательно в уме):
Отказ от статических структур и от структур как таковых, одни объекты, либо добавление хитрых механизмов для работы с ними.

Не, не понял. Что такое статические структуры?

Цитата: Comdiv
Добавление конструкторов, да не простых, а с инициализацией всех данных объекта.

Не. Можно без конструкторов. Просто синтаксис для инициализации рекордов. Если полей много - делается обычная вспомогательная функция-конструктор. Ничего в язык добавлять не надо.

Цитата: Comdiv
Объявление данных модуля с инициализацией.
Отказ от данных модуля, которые  не могут быть инициализированы по месту.

Не, не понял. Обсуждаемые свойства никак не мешают данным модуля - всегда есть OPTIONAL. Просто теперь все будет явно: если данные модуля не могут быть проиничены самостоятельно - то они OPTIONAL.

Цитата: Comdiv
Как-то придумать инциализацию по месту массивов, или отказ от них.

Да, да. Давно пора нормально инициализировать массивы :) Если массив большой - да, есть проблема в дополнительных накладных расходах. Но мне не кажется, что это что-то принципиальное. Ну зачем может быть нужен неинициализированный большой массив? Жуткую матрицу посчитать? Так оно считать будет много дольше, чем инициализировать.

Цитата: Comdiv
Отказ от 1-го RETURN (Оберон ведь движется в этом направлении)

А может это неправильное направление? :)

Цитата: Comdiv
Возможно, что-то ещё.

Про исключения не понял, почему нельзя возвращать код ошибки вместе с результатом?

Потому что результат будет "мусорным" в случае ошибки. А мы не хотим мусорных значений.

Цитата: Comdiv
По-моему вырисовывается не диалект Оберона, а совсем другой язык.

Да ладно. До какого-нибудь С++ или жабы такому диалекту очень далеко :) А определенные проблемы решаются.

Цитата: Comdiv
Предложу свои варианты ответов:
1.При необходимости многие будут не выкручиваться в эквивалентные преобразование кода, а инициализировать по месту мусорно, что затруднит обнаружение ошибки, в случае если переменная так и не будет проинициализирована нормально (за что боролись, на то и напоролись).

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

Цитата: Comdiv
2.Усложнение языка и компилятора, ради небольшой проблемы. Ведь изначально шла речь о простом изменении, существенно более простом, чем то, что реализовано в анализаторе BlackBox или компиляторе java. А если нам нужен другой язык, с кортежами, исключениями, nullable типами и другими фишками, это другой вопрос.

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

Цитата: Comdiv
3.Возможно, что-то ещё. Мне не так-то просто предвидеть все последствия от необходимых изменений.

В том, что я описал, нет ничего нового. Оно в том или ином виде присутствует в существующих ЯП. Так что каких-то злобных последствия я не предвижу.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 22, 2011, 08:33:50 pm
В LLVM кортэжи есть сразу. Вообще кортэж, для компилятора, и вообще на низком уровне штука весьма простая и ничем принципиально от тех же структур не отличается.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Валерий Лаптев от Февраль 23, 2011, 05:55:54 am
Вставлю свои 5 копеек:
1. Инициализацию модульных переменных можно делать в секции инициализации модуля - я правильно понимаю? Придумывать для этого специальный синтаксис - не обязательно.  Хотя, конечно, можно это повесить на компилятор - пусть из инициализатора сделает преобразование в секции инициализации модуля.
2. Объявление по месту - мне нравится.
3. Объявление с инициализацией - ИМХО только для встроенных типов. Тем более, что это опять можно повесить на компилятор - пусть разнесет объявление и инициализацию.

Соответственно 4 - никаких конструкторов! Или надо МНОГО думать, как их ограничить. В С++ конструкторы вызываются по умолчанию, что есть зло. Единственное ограничение, которое программер может употребить - это explicit. Но не обязательно, поэтому мало кто пишет, особенно начинающие.
Соответственно 5 - нет необходимости в механизме исключений.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Сергей Прохоренко от Февраль 23, 2011, 10:47:18 am
Соответственно 5 - нет необходимости в механизме исключений.

Вы теперь против механизма исключений, даже такого  (http://sites.google.com/site/purebuilder/#TOC-28)сильно ограниченного функциональным стилем и "скрещенного" с кодами ошибки, как в PureBuilder?

Возникает несколько вопросов:
1) Что взамен - для действительно аварийных ситуаций, делающих бессмысленным возвращаемое значение функции?
2) Что изменить в языке, чтобы код обработки ошибок в рантайме был отделен в программе от нормального штатного кода?
3) Как же тогда учить студентов осторожному применению механизма исключений в "промышленных" языках?
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 23, 2011, 01:47:10 pm
Вставлю свои 5 копеек:
1. Инициализацию модульных переменных можно делать в секции инициализации модуля - я правильно понимаю? Придумывать для этого специальный синтаксис - не обязательно.  Хотя, конечно, можно это повесить на компилятор - пусть из инициализатора сделает преобразование в секции инициализации модуля.

Я бы повесил на компилятор - инициализация модульных переменных в порядке объявления, затем вызов секции инициализации.

Цитата: Валерий Лаптев
2. Объявление по месту - мне нравится.
3. Объявление с инициализацией - ИМХО только для встроенных типов. Тем более, что это опять можно повесить на компилятор - пусть разнесет объявление и инициализацию.

Не понял. Почему только для встроенных типов и зачем разносить?

Цитата: Валерий Лаптев
Соответственно 4 - никаких конструкторов!

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

Цитата: Валерий Лаптев
Соответственно 5 - нет необходимости в механизме исключений.

Нет, механизм исключений принципиален. Если функция возвращает ненулевой указатель, то что ей вернуть, если произошла ошибка? Без исключений вся идея nullable типов и инициализации только осмысленными значениями не работает.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 23, 2011, 03:34:37 pm
Про инициализацию массивов... Что мешает сделать ленивую инициализацию? Т.е. инициализация данной ячейки массива непосредственно ПЕРЕД чтением. Если данную ячейку вначале не читают, а скажем сразу туда пишут, то оверхеда не будет вообще.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 23, 2011, 06:32:34 pm
Ответ на оригинальный пост в http://forum.oberoncore.ru/viewtopic.php?p=60599#p60599 (http://forum.oberoncore.ru/viewtopic.php?p=60599#p60599)

Цитата: Илья Ермаков
Цитата: Сергей Прохоренко
foreach'и бывают разными. Может быть, Вы имели дело с неудачными, и надо сделать (или позаимствовать) другой вариант? Например, с не столь безальтернативной "отначаладоконцовостью"?
Так это будет WHILE и райдер, как раз.

foreach - это райдер-итератор, спаянный намертво с циклом, при этом с циклом, который идёт от начала до конца.
Максимально специализированная вещь. Если, конечно, не разрешать "стоп-кран" break и "прыжки из поезда на ходу".

Максимально специализированная вещь - это как раз очень хорошо. Особенно, если она максимально специализирована для 90% случаев использования в конкретном проекте :)
foreach дает возможность максимально удобно обработать значения элементов последовательности. И больше ничего. Причем его основное достоинство именно в этом "ничего", а не в краткости записи :) Он не даст вам неправильно выбрать следующий элемент, он не даст вам изменить значение этого элемента, он не даст вам неправильно прописать условие завершение цикла. Он не даст вам совершить кучу ошибок. А в качестве бонуса - читающий ваш код сразу увидит, что вы не делаете здесь ничего неожиданного (см. список чего foreach "не даст") - и спокойно пойдет читать дальше более интересные вещи.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Berserker от Февраль 23, 2011, 06:43:17 pm
Как всё сложно.

Цитировать
[17.1] What are some ways try / catch / throw can improve software quality?

FAQ: You'll have less if statements in your code: you won't have to check for errors each time you call a function. Conditional statements are known to contain more bugs than other statements. With less if tests, you'll ship a better product, faster.

FQA: This is cargo cult programming. Conditional statements are error-prone because they are used to handle complicated scenarios, where an action can result in many different outcomes, which affect the next actions. In order to make errors less probable, one has to simplify the model of the desired behavior of the software. The problem is the complexity that leads to if statements, not the if keyword, and using different keywords is not going to solve the problem by itself.

Exceptions are supposed to simplify the error handling model based on the assumption that in most cases, a function that detected an error can't handle it, and has to propagate it to the caller. Finally, a "high-level" enough caller is reached and actually makes a decision (pops up an error message, tries a different action, etc.).

Despite its promises, this approach has inherent problems. There's a "social" problem - with exceptions, people are not aware of the different errors that may happen in the code because most of the code doesn't deal with errors. And when people rarely think about a particular aspect of an application, ultimately this aspect is unlikely to be handled well. There's a more "technical" problem - functions essentially doing nothing upon error except for propagating errors to the caller still can't be completely unaware of errors. That's because they may need to release the resources they acquired before returning to the caller, which may lead to more errors, which must also be handled. Finally, in practice exception support has run-time overhead, and very significant code size overhead, even if exceptions are never raised at run time, and even if they are not mentioned in your code. C++ devotees may claim otherwise; you can check by compiling your code with and without exception support (if your compiler doesn't have such a flag, compile code as C and as C++ instead). This is unacceptable in resource-constrained systems.
Отрицательный результат - тоже результат. И хотя нас часто порывает принять за данность выполнение программы в идеальном окружении с идеальным пользователем, а всю логику обработки ошибок закинуть как можно выше, это не выход. Пора уже понять, что практически все функции не способны гарантировать результат. Что исключения одного класса обезличиваются при всплывании, превращаясь в нечто вроде TIOError. Что если мы хотим обработать 250 вызовов функций по-разному, нам понадобятся 250 обработчиков и их логика должна быть на том же уровне, что и вызов функций.

Посмотрите на самые азы - арифметику. +, -, * - возможность выхода за границы типа (переполнение), / - тоже + деление на 0. Практически каждая функция из rtl в php может вернуть ошибку. Работа со строками, массивами, форматами - чем угодно. Если возвращаемое значение функции и есть её результат, то механизм исключений будет использоваться всегда. Или же его тросянка. Часть функций с кодами ошибок, другая на исключениях. Вопрос. А что есть исключение? То, что сейчас модно называть исключением, является ничем иным как штатной ситуацией. Зачем вводить исключения, потом для них же магические способы финализации, затем перегрузку операторов, которая без исключений вообще нежизнеспособна. Затем возвращение сложных структур функциями. Что более фундаментально? Что автономно? Что проще в реализации? С какой кстати высший уровень должен знать все типы исключений низших, а если не знать, то иметь лишь единственный молчаливый способ их обработать? Наконец, зачем ещё один goto на адрес в стёковой структуре, когда стремимся к безопасному, надёжному и наглядному коду, где прыжкам в неизвестность просто не место.

P.S Кстати, пример изначально неверного подхода к проектированию можно увидеть в обероновском модуле Files. Там функции работают с идеальной файловой системой и понятия ошибки нет вообще.

Заключение: для действительно исключительных ситуаций (определённого класса) достаточно функций-финализаторов.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Февраль 23, 2011, 06:59:10 pm
Цитата: vlad
С рекордами можно жить (я в С++ живу, хотя там есть boost::tuple). Писанины чуть больше, зато поля именованы, зачастую это повышает читабельность. Существенной переработки применительно к оберону не надо, достаточно иметь синтаксис для инициализации рекордов (так же как и массивов). Этот недостающий сахар уже обсуждали - без него неудобно и в классическом обероне.
1.Необходимость больше писать приведёт к тому, что фишкой не будут пользоваться. Перепишите пример со структурами и сравните. Вспомните хотя бы, как сишники жалуются на "многословность" синтаксиса Оберона. 2.Как минимум нужно и объявление типа по месту.

Цитировать
Чего ж там сложного??? Компилятор уже умеет иметь дело с временными переменными (для вычисления выражений). Объявление по месту - такая же временная переменная.
Не знаю, не пробовал реализовать, но интуитивно чувствую, что не очень это просто для понимания компилятора, когда группу чего-то отдельного, можно представить как одно и наоборот. Тернарный оператор намного проще, особенно если не как в С, а как-то так :
Цитировать
TOP(condition, value1, value2);

Цитировать
Не, не понял. Что такое статические структуры?
Правильнее было сказать: статически объявленные экземпляры структур, т.е. не в динамической памяти (затрудняюсь более грамотно сформулировать)

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

Цитировать
Не, не понял. Обсуждаемые свойства никак не мешают данным модуля - всегда есть OPTIONAL. Просто теперь все будет явно: если данные модуля не могут быть проиничены самостоятельно - то они OPTIONAL.
Что не понятно, конечно optional всегда может инициализироваться по месту, что и скрашивает отказ от данных, которые не могут. Тем не менее, данные могут гарантировано инициализироваться в секции инициализации, но они всё равно должны объявляться через optional. Это точно не влечёт дополнительных расходов со стороны программиста и программы в виде явных и неявных проверок/приведений типа?

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

Цитировать
Цитата: Comdiv
Отказ от 1-го RETURN (Оберон ведь движется в этом направлении)
А может это неправильное направление? :)
Правильное. Не могу припомнить сколь-нибудь серьёзную проблему, связанную именно с неинициализированной переменной, а вот функции по нескольку тысяч строк, плохо поддающиеся пониманию и переработке из-за усеянности на самом деле ненужными return-ами мне встречаются регулярно. Надо ведь помогать программисту правильно, не так ли?

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

Цитировать
В том, что я описал, нет ничего нового. Оно в том или ином виде присутствует в существующих ЯП. Так что каких-то злобных последствия я не предвижу.
В том-то и дело, что включались эти средства по большей части без большого осмысления (говорю это, основываясь ни на чём), а комбинации с запретом на неинициализацию вряд ли есть где-то. Многие не видят и более простых последствий и в ус не дуют. В языке С++ тоже уже сюрпризов нет, а писать на нём хотят всё меньше.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 23, 2011, 08:02:39 pm
1.Необходимость больше писать приведёт к тому, что фишкой не будут пользоваться. Перепишите пример со структурами и сравните. Вспомните хотя бы, как сишники жалуются на "многословность" синтаксиса Оберона.

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

Цитата: Comdiv
2.Как минимум нужно и объявление типа по месту.

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

Цитата: Comdiv
Цитировать
Чего ж там сложного??? Компилятор уже умеет иметь дело с временными переменными (для вычисления выражений). Объявление по месту - такая же временная переменная.
Не знаю, не пробовал реализовать, но интуитивно чувствую, что не очень это просто для понимания компилятора, когда группу чего-то отдельного, можно представить как одно и наоборот.

Для понимания компилятора там самое сложное - разобраться с областями видимости. А так.. не знаю... ИМХО все просто.

Цитата: Comdiv
Тернарный оператор намного проще, особенно если не как в С, а как-то так :
Цитировать
TOP(condition, value1, value2);

Ну такая функция все равно будет встроенной, так что не знаю, ИМХО не должно быть трудностей.

Цитата: Comdiv
Правильнее было сказать: статически объявленные экземпляры структур, т.е. не в динамической памяти (затрудняюсь более грамотно сформулировать)

Ну так - инициализировать при объявлении. Что не так?

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

Ну, допустим у нас есть такой синтаксис для инициализации:
TYPE X = RECORD a: INTEGER; b: INTEGER; END
...
VAR x:= X{1, 2}; // локальная переменная

Выделение в хипе:
VAR x:= NEW(X{1, 2});

Функция-конструктор:
PROCEDURE construct_x(): X
BEGIN
    RETURN X{1, 2};
END construct_x

Расширение записи (Y наследуется от X с добавлением одного поля):
VAR y:= Y{X{1, 2}, 3}; // локальная переменная

Использование функции конструктора:
PROCEDURE construct_y(): Y
BEGIN
    RETURN Y{construct_x(), 3};
END construct_y

Цитировать
Тем не менее, данные могут гарантировано инициализироваться в секции инициализации, но они всё равно должны объявляться через optional. Это точно не влечёт дополнительных расходов со стороны программиста и программы в виде явных и неявных проверок/приведений типа?

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

Цитировать
К примеру, транспонирование матрицы - штука быстрая. А если это массив структур, содержащих массивы?

Не, хочется реального примера :) Мне больше видятся всякие низкоуровневые штуки, когда надо скормить кусок памяти драйверу и т.п. Но для таких случае всегда есть SYSTEM :)

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

Дык, согласитесь, что оригинальная проблема в функциях на 1000 строк, а не в RETURN. Думаю вы бы скорее согласились сопровождать функции на 10 строк с RETURN, чем на 1000 строк без RETURN? ;)

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

Человеком ваш код тоже воспринимается непросто. Лично мне понятнее переделанный вариант.

Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 23, 2011, 09:14:17 pm
1.Необходимость больше писать приведёт к тому, что фишкой не будут пользоваться. Перепишите пример со структурами и сравните. Вспомните хотя бы, как сишники жалуются на "многословность" синтаксиса Оберона.

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

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

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

Если в языке кортеж это больше, чем анонимная структура с анонимными полями - то наверное из нее можно выжать что-то сильно полезное. Например, если представить, что в нашем случае список инициализации - это на самом деле кортеж. Или пойти еще дальше: вызов функции это на самом деле вызов функции с одним аргументом - кортежем. Но я пока не готов настолько глубоко копать...
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Февраль 23, 2011, 11:30:01 pm
Отрицательный результат - тоже результат. И хотя нас часто порывает принять за данность выполнение программы в идеальном окружении с идеальным пользователем, а всю логику обработки ошибок закинуть как можно выше, это не выход.

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

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

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

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

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

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

Действительно, с какой кстати? И почему единственный? Сколько надо - столько и сделаем. Обычно достаточно единичных обработчиков на кучу кода. И почему молчаливый? Как захотим - так и сделаем.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Илья Ермаков от Февраль 24, 2011, 05:50:23 pm
Если в языке кортеж это больше, чем анонимная структура с анонимными полями - то наверное из нее можно выжать что-то сильно полезное. Например, если представить, что в нашем случае список инициализации - это на самом деле кортеж. Или пойти еще дальше: вызов функции это на самом деле вызов функции с одним аргументом - кортежем. Но я пока не готов настолько глубоко копать...

В JavaScript во многих библиотеках (Rich Web и т.п., например, Qooxdoo) функции часто параметризуются объектами.
Т.е. типа: var panel = new qx.ui....Panel({width: 200, height: 300}).
Вообще, достаточно удобно и единообразно получается.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: valexey от Февраль 24, 2011, 06:03:09 pm
Вообще, у например F# все функции внешних .нет либ вызываются именно как функция с одним аргументом-картежем значений.
mFile.MenuItems.Add(miOpen)

Тут (miOpen) это именно что кортеж с одним элементом внутри. Нормальный вызов функции с параметром-не кортежем в F# выглядит так:
mFile.MenuItems.Add miOpen
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Март 02, 2011, 06:34:39 pm
Цитировать
Ну вот я пишу на питоне тоже, там есть родные (лаконичные) кортежи. Пользуюсь ими все равно не очень часто (хотя пишу в обсуждаемом стиле - все инициализируется чем-то осмысленным).
Основной недостаток - если такой кортеж пошел гулять за пределы двух/трех функций, то понять смысл того, что там лежит становится трудно.
Именованная структура все же лучше. Опять же - ваш оригинальный пример довольно экстремальный. Так что острой необходимости в кортежах я не вижу.
Нет ничего экстремального в инициализации по одному условию нескольких переменных и по смыслу не объединяемых в одну сущность. Ну, строго говоря, острой необходимости нет не только в кортежах, но и в...



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


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

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

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

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

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

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

Вспомнил о ещё одной неудобности. В Обероне значение переменных можно менять, передавая их через параметры в процедуры. Легко представить ситуацию, когда такими процедурами можно также инциализировать, но при таком подходе получится это только с накладными расходами.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Март 03, 2011, 11:51:33 pm
Цитировать
Опять же - ваш оригинальный пример довольно экстремальный. Так что острой необходимости в кортежах я не вижу.
Нет ничего экстремального в инициализации по одному условию нескольких переменных и по смыслу не объединяемых в одну сущность. Ну, строго говоря, острой необходимости нет не только в кортежах, но и в...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Опять же - поясните, что за накладные расходы такие. В каком месте.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Март 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 изменение ), но я уже написал про ваш хитрый автоматический механизм, так что надо.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Март 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 (объявление/инициализация/присваивание) накладные расходы при прочих равных будут больше, согласен. Зато есть гарантия, что структура не останется проинициализированной наполовину.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Март 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;
      }
 }
}
И ещё раз спрошу, если скорость не важна, зачем вообще статические данные?
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Март 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;
      }
 }
}
И ещё раз спрошу, если скорость не важна, зачем вообще статические данные?

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

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

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

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

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

Это не провокация. Это желание показать, что это не настолько принципиальная проблема. Да, я признаю, что такой подход не всегда будет удобен и конечно у него есть свои недостатки. Но я говорю о том, что он менее "проблемный" (по моему мнению), чем существующий сейчас в обероне (отдельная секция VAR, неинициализированные переменные).
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Илья Ермаков от Март 26, 2011, 09:33:19 pm
В циклах - это будут локальные переменные цикла. При этом, как мы выяснили, даже в случае структур никаких проблем с производительностью не будет. Если же речь идет о внешней (по отношению к циклу) переменной-структуре, то мне очень трудно представить пример, когда на каждом шаге цикла надо будет ее присваивать новому значению.

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

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

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

Ну извините :) Тем хуже для правильных циклов :)
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Илья Ермаков от Март 28, 2011, 08:39:40 pm
Да, тут ваши "привильные" циклы с дублированием кода для первого шага и последующих - будут плохо работать :)

Правильность, в естественнонаучном смысле, не может зависеть от "наши-ваши" :)
Дублирование отображает элементарный объективный факт, разницу на 1 между количеством некоторых операций в развёртке некоторого процесса, грамматикой которого является алгоритм. Хоть убиццца ап стену, но если природа процесса такова...

Если, конечно, хорошо понимать дело, то можно предложить кое-что, как это сделал, например, Пётр Алмазов:
http://forum.oberoncore.ru/viewtopic.php?f=86&t=3159
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: vlad от Март 28, 2011, 08:50:45 pm
Да, тут ваши "привильные" циклы с дублированием кода для первого шага и последующих - будут плохо работать :)

Правильность, в естественнонаучном смысле, не может зависеть от "наши-ваши" :)

Не хотелось бы опять обсуждать циклы. Поэтому ответ такой: если имеет место копирование структуры (уже существующей, потому что она нам нужна до или после цикла) и оно тормозит (потому что оно в цикле и цикл больше ничего полезного не делает), то можно завести "дублера", который будет переинициализировать поля существующей структуры.
Название: Re:Приспособим PureBuilder для разработки игр
Отправлено: Comdiv от Март 30, 2011, 06:21:46 pm
В циклах - это будут локальные переменные цикла. При этом, как мы выяснили, даже в случае структур никаких проблем с производительностью не будет. Если же речь идет о внешней (по отношению к циклу) переменной-структуре, то мне очень трудно представить пример, когда на каждом шаге цикла надо будет ее присваивать новому значению.
Ну представьте себе, к примеру, любой циклический алгоритм нахождения числа(пусть Фибоначчи), для длинных чисел. Можете пофантазировать на тему, когда массивы в числах динамические и статические.

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