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

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #15 : Февраль 17, 2011, 01:11:51 pm »
Т.е. программа должна получаться верна по построению. Не должно быть зацикливаний, выходов за границы, численных переполнений.

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

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #16 : Февраль 17, 2011, 01:16:20 pm »
Тут есть отличие -- знаем мы что оно зациклилось, или не знаем. Если знаем, тогда ждать смысла не имеет, надо убить (если зациклилось), если мы гарантировано знаем что алгоритм конечный, то можем подождать. Более того, можем как-то проследить процесс исполнения и что-то спрогнозировать. Т.е. процесс получаем управляемый.

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

P.S. Хотя, конечно, иметь гарантии завершимости на этапе компиляции было бы полезно. Сколько-то ошибок/опечаток не пролезло бы.

Сергей Прохоренко

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

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

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

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

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #18 : Февраль 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;
    }
}
Т.о. нуль оно не возвращает никогда. Всегда возвращается некое осмысленное значение. Это не панацения конечно, но это сильно помогает отладке и диагностике ошибок. Работа программы становится вроде как более предстказуемой с случае ошибки.

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

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #19 : Февраль 17, 2011, 01:45:40 pm »
Я против такой имитации решения проблемы.  :-\\

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

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

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

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

P.S. Еще хочу сказать, что такой подход (тотальная инициализация и ненулевые указатели) уже несколько лет успешно обкатан мной лично на практике. Реально "ненужных" присваиваний (нулевых) чрезвычайно мало - они возникают у меня только на стыке с Win API, когда какая-то переменная будет заведомо проинициализирована вызовом функции, но я ее все равно инициализирую в 0, чтобы не нарушать стиль. Проблема только в том, что в случае С++ это вопрос стиля - компилятор позволяет так писать, но не требует.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #20 : Февраль 17, 2011, 01:50:30 pm »
К сожалению Ява, в отличае от например Ады, не позволяет определить тип ненулевой ссылки. А тут бы оно было бы очень полезно. Поэтому среди Адовцев Ява считается языком маленьким и слабеньким :-)

Угу. Глядя на жабовский/обероновский код, в который пришел указатель, никогда не сможешь сказать, что здесь никогда не будет "null dereference exception". Потому что нет _типа_ ненулевых указателей.
« Последнее редактирование: Февраль 17, 2011, 01:52:23 pm от vlad »

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #21 : Февраль 17, 2011, 02:12:42 pm »
Цитата: Сергей Прохоренко
Мы говорим о разных вещах. Длинных типов обычно даже слишком много разных, что ведет к несовместимости по типу. Поэтому, например, Вирт все их просто отбросил в Обероне-07. Ему это было сделать просто - он ведь не разрабатывает игры - ему и не нужны длинные типы.

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

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

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

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

Сергей Прохоренко

  • Newbie
  • *
  • Сообщений: 16
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #22 : Февраль 17, 2011, 02:35:03 pm »
Я думаю, что нужно предоставить программисту удобную возможность проинициализировать переменную при объявлении и напомнить ему, если это не сделано. Но принуждать к инициализации не нужно. Иначе в рантайме уже не удастся сгенерировать и обработать исключение, когда действительно осмысленная инициализация не прошла. Программа будет утверждать, что "всё хорошо, прекрасная маркиза", хотя на самом деле это не так.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #23 : Февраль 17, 2011, 02:39:44 pm »
Я думаю, что нужно предоставить программисту удобную возможность проинициализировать переменную при объявлении и напомнить ему, если это не сделано. Но принуждать к инициализации не нужно. Иначе в рантайме уже не удастся сгенерировать и обработать исключение, когда действительно осмысленная инициализация не прошла. Программа будет утверждать, что "всё хорошо, прекрасная маркиза", хотя на самом деле это не так.

Давайте зайдем от обратного :) Придумайте пример, когда вы не можете осмысленно инициализировать переменную сразу. Мы над ним помедитируем :) Рассмотрим достоинства и недостатки.

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #24 : Февраль 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);
}

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #25 : Февраль 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);
}

Comdiv

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #26 : Февраль 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);
}

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #27 : Февраль 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);
}

Валерий Лаптев

  • Jr. Member
  • **
  • Сообщений: 58
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #28 : Февраль 17, 2011, 08:12:06 pm »
Собственно я говорил именно об этом. Именно эти числа, о которых вы говорите есть сразу в Haskell и Erlang'e. Функция подсчета факториала от 5ти будет одинаково использоваться и для подсчета от 10000. В первом случае будет использован int32, во втором случае, начиная с некоторого шага, будет использовано длинное целое (переменной длины). При этом тип останется тот же -- Integer.
Мы в семантическом редакторе реализуем учебный язык без привязки к размерам встроенных типов. Я поначалу хотел даже отказаться от деления на целые и дробные, и оставить один тип Число. Но мне показалось, что это слишком радикально - все же во всех языках числа не менее двух типов.   

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Приспособим PureBuilder для разработки игр
« Ответ #29 : Февраль 17, 2011, 08:16:28 pm »
Собственно я говорил именно об этом. Именно эти числа, о которых вы говорите есть сразу в Haskell и Erlang'e. Функция подсчета факториала от 5ти будет одинаково использоваться и для подсчета от 10000. В первом случае будет использован int32, во втором случае, начиная с некоторого шага, будет использовано длинное целое (переменной длины). При этом тип останется тот же -- Integer.
Мы в семантическом редакторе реализуем учебный язык без привязки к размерам встроенных типов. Я поначалу хотел даже отказаться от деления на целые и дробные, и оставить один тип Число. Но мне показалось, что это слишком радикально - все же во всех языках числа не менее двух типов.   
Во многих языках тяготяющик к скриптовому применению, есть только просто число. Например в той же Lua. И мне кажется, что даже в js это так, но тут могу ошибаться.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"