WH>Здравствуйте, c-smile, Вы писали:
CS>>Вопрос №1: пассаж про new Tuple ... в теле цикла я не понял. WH>Если посмотришь внимательно то это не единственное место к которому можно докопаться. CS>>Зачем думатель это придумал? WH>Главное то что думатель вывел все типы, а то что думатель сделал несколько локальных ляпов так это детская болезнь. Просто у ребят физически не хватает ресурсов для того чтобы сделать оптимизацию таких вещей и по этому их компилятор генерирует код по принципу "что вижу то пою". WH>Уверен что к релизу они эти ляпы исправят.
Не уверен.
В условиях недетерминированного описания (типов в том числе) думатель
будет вынужден "стелить соломку".
Т.е. в принципе чем меньше информации имеет компилятор тем менее оптимальный
код он строит. Более универсальный — да.
VD>>>Получаем краткость скриптов, и мощь компилируемых языков. CS>>Такая компиляция это не мощь. WH>А что же? В программе не указано ни одного типа... тем не мение компилятор сгенерировал строго типизированный код. Если это не мошь тогда что же такое мощь?
Вопросы:
1) Что сделает думатель если увидит скажем такое:
hash[key] = flag? 1: "string";
2) C intellisense как я понимаю такой вывод типов дружить не будет?
Т.к. типы становятся известны только после построения syntax tree всей программы.
И философическая часть:
Зачем в принципе нужен такой выводитель типов?
Какие задачи он призван решить или облегчить их решение?
Какие есть средства "детерминизаци": "я хотел сказать А а думатель придумал Б".
Личное замечание:
Такая недетерминированность в C++ является источником очень неприятных и дурных ошибок.
Один раз очень долго искал в чем проблема. Оказалось в наличии двух конструкторов у
объекта: cls(int n) и cls(bool b). (или что-то подобное — не помню)
Я имел ввиду одно а думатель молча выводил другой тип... Причем разные думатели
(компиляторы) думали по разному.
Re: Философический вопрос про автоматический вывод типов.
Здравствуйте, c-smile, Вы писали:
CS>Личное замечание: CS>Такая недетерминированность в C++ является источником очень неприятных и дурных ошибок. CS>Один раз очень долго искал в чем проблема. Оказалось в наличии двух конструкторов у CS>объекта: cls(int n) и cls(bool b). (или что-то подобное — не помню) CS>Я имел ввиду одно а думатель молча выводил другой тип... Причем разные думатели CS>(компиляторы) думали по разному.
Вот еще один пример "из жизни" (я его, конечно, схематизировал), связанный с этой стороной Си++.
Компилятор спокойно приводит bool к float, как будто так и надо.
#include <stdio.h>
class Float {
float _float;
public:
Float(float x) : _float(x) { }
// следующая строка была закомментирована по ошибке (просто опечатка)
//operator float() { return _float; }
// в реальной программе bool() проверяет отличие Float от нуля
// чтобы обеспечить корректную работу конструкции if (F) ...operator bool() { return (_float != 0); }
};
int main()
{
Float F = 3.1415926536f; // Кто и шутя, и скоро пожелаетъ Пи узнать число, ужъ знаетъ.float x = F;
printf("%f\n", x); // Что напечаталось? Правильно, 1.000000return 0;
}
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Хоар
Re[2]: Философический вопрос про автоматический вывод типов.
Здравствуйте, AVC, Вы писали:
CS>>Один раз очень долго искал в чем проблема. Оказалось в наличии двух конструкторов у CS>>объекта: cls(int n) и cls(bool b). (или что-то подобное — не помню) CS>>Я имел ввиду одно а думатель молча выводил другой тип... Причем разные думатели CS>>(компиляторы) думали по разному.
AVC>Вот еще один пример "из жизни" (я его, конечно, схематизировал), связанный с этой стороной Си++. AVC>Компилятор спокойно приводит bool к float, как будто так и надо.
Люди, зачем вы валите все с больной головы на здоровую? Вот такой пример не скомпилируется, компилятор найдет обе ошибки:
В Nemerle семантика в данном случае похожа на C#(а может и вообще совпадает). Есть неявное приведение типов, но только для числовых типов(int, float, double, и т.п.) и таких проблемы как в C++ с неявным приведением нет и быть не может. Ни char, ни bool, ни что-либо подобное числовыми типами не считается и подобная ошибка абсолютно исключена(привести к числовым эти типы можно только насильно). Так что это проблема только C/C++.
Re: Философический вопрос про автоматический вывод типов.
Здравствуйте, c-smile, Вы писали:
CS>В условиях недетерминированного описания (типов в том числе) думатель CS>будет вынужден "стелить соломку".
Такий условий нет "бай-дизайн". Любое разночтение интерпретируется как ошибка. "Думатель" делает выводы только если ситуация полностью детерминирована.
CS>Т.е. в принципе чем меньше информации имеет компилятор тем менее оптимальный CS>код он строит. Более универсальный — да.
Так как ситуация всегда детерминирована, то компилятор всегда может оптимальный код. Лиш бы он умел это делать. Так что твои выводы не верны.
CS>Вопросы: CS>1) Что сделает думатель если увидит скажем такое: CS> hash[key] = flag? 1: "string";
Для Нэмерла этот код будет "звучать" так:
hash[key] = if (flag) 1 else"string";
и на него компилятор банально гавкнет:
expected int-, got string in computation branch: common super type of types [int, string] is a set of interfaces
то есть, просто не даст так сделать.
CS>2) C intellisense как я понимаю такой вывод типов дружить не будет?
А какая разница то кому делать вывод типов? Будет такой же вывод делать парсер интелисенса.
В первй строке он конечно ничего умного не предложит. Но в следующих уже предложет.
К тому же всегда можно задать тип при его создании. Только в отличии от большинства других языков однин раз.
def hash = Hashtable<string, int>();
а не
Hashtable<string, int> hash = Hashtable<string, int>();
как это сейчас происходит в С++ и C#.
CS> Т.к. типы становятся известны только после построения syntax tree всей программы.
Они приципиально до этого не доступны. Любой интелисенст парсет все файлы проекта и крайне плохо относится к наличию ошибок в них.
Собственно пока типы ключей и значений имеют которкие имена, то замусоривания не так видно. Но когда это длинные типы темблее сами содержащие длиннющие параметры типов, то выходит довольно ужасно выглядящий код. Например, объявление той же хэш-таблицы может переноситься на две строки, чтобы влезнь в правила форматирования заставляющие переносить строки по 80 символов. C#:
Dictionady<MyFirstClassWithLongName<List<MySecondClassWithLongName>>, List<MySecondClassWithLongName>> dic =
new Dictionady<MyFirstClassWithLongName<List<MySecondClassWithLongName>>, List<MySecondClassWithLongName>>();
dic.Add(var1, var2);
C++:
Dictionady<MyFirstClassWithLongName<List<MySecondClassWithLongName^>>^, List<MySecondClassWithLongName^>>^ dic^ =
new Dictionady<MyFirstClassWithLongName<List<MySecondClassWithLongName^>>^, List<MySecondClassWithLongName^>>^ ();
dic->Add(var1, var2);
Nemerle:
def dic = Dictionady();
dic.Add(var1, var2);
CS>И философическая часть:
CS>Зачем в принципе нужен такой выводитель типов?
Чтобы писать такой же краткий код как на динамически типизрованных языках, но при этом иметь все приемущества статически типизированных, в том числе быстрый код и интелисенс.
CS>Какие задачи он призван решить или облегчить их решение?
Очистить код от лишних конструкций сделав его более кратким и понятным. При этом как бы не запрещается описывать типы более часто.
Это как бы развитие идеии которую пытаются протлкнуть в следующую версию С++ (ключевое слово auto).
Собственно приведенный пример скорее демонстрация ума компилятора. Рельно же приемущество получается когда начинашь описывать вложенные методы. Например, я даже не знаю как типизированно описать следующую конструкцию:
А так спокойно описал. И выглядит кратко.
CS>Какие есть средства "детерминизаци": "я хотел сказать А а думатель придумал Б".
Компилятор ничего не выдувывает. Это ты думатель. А он дететриминованный конечный автомат.
Ты можешь помочь ему задв тип при объявлении переменой, а можешь положиться на его "разумность".
CS>Личное замечание: CS>Такая недетерминированность в C++ является источником очень неприятных и дурных ошибок.
В Нэмерле нет недетерминированностей. Точнее если и есть, то по шибке. Авторы их не планировали.
А С++ спроектирован так... Короче о нем просто не хочу говорить.
CS>Один раз очень долго искал в чем проблема. Оказалось в наличии двух конструкторов у CS>объекта: cls(int n) и cls(bool b). (или что-то подобное — не помню) CS>Я имел ввиду одно а думатель молча выводил другой тип... Причем разные думатели CS>(компиляторы) думали по разному.
Не пишите на дурно спроектированных языках и не будете искать шибки очень долго.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Философический вопрос про автоматический вывод типов.
Думаю твой пример на этом: AVC>Вот еще один пример "из жизни" (я его, конечно, схематизировал), связанный с этой стороной Си++.
можно было бы и закончить.
К тому же ты сам усугубил свою проблему создав неявное приведение к bool.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Философический вопрос про автоматический вывод типов.
typedef Dictionady<MyFirstClassWithLongName<List<MySecondClassWithLongName^>>^, List<MySecondClassWithLongName^>>^ MyDictionaryPtr;
...
MyDictionaryPtr dic^ = new MyDictionaryPtr;
VD>Собственно приведенный пример скорее демонстрация ума компилятора. Рельно же приемущество получается когда начинашь описывать вложенные методы. Например, я даже не знаю как типизированно описать следующую конструкцию: VD>
После программирования с RubyOnRails я думаю, что это не есть хорошо. Там так же классы-модели возвращают какие-то объекты, которые затем используются формами для отображения информации. И очень скоро без явного декларирования типов возвращаемых объектов напрочь забываешь, что окуда возвращается и как с этим можно работать. А уж поддерживать целостность всего этого дела можно только за счет обилия unit-тестов. Приведенный тобой пример очень похож на эту ситуацию.
VD>Не пишите на дурно спроектированных языках и не будете искать шибки очень долго.
Ага, а пока появятся хорошо спроектированные языки не программируйте ничего.
И совсем уж философский вопрос: неужели за все время развития программирования еще не было создано ни одного нормально спроектированного языка?
И что заставляет думать, что через некоторое время кажущийся нормально спроектированным язык не окажется объявленным дурно спроектированным?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Философический вопрос про автоматический вывод типов.
Disclaimer: Nemerle знаю только на основе предыдущих постов, сказанное ниже оносится скорее к O`Caml. Думаю, это не будет оффтопиком, так как проблема обсуждается с глобальной точки зрения
CS>Не уверен. CS>В условиях недетерминированного описания (типов в том числе) думатель CS>будет вынужден "стелить соломку". CS>Т.е. в принципе чем меньше информации имеет компилятор тем менее оптимальный CS>код он строит. Более универсальный — да.
В том-то и дело, что компилятор выводит недостающую информацию. Например, он может вывести что ты кладешь в массив только числа и сгенерировать код работы с массивом, оптимизированный под работу с числами. В то же время в Java ты вынужден либо писать свою специализацию, либо терять производительность на боксинге.
Вообще, почитай про реконструкцию типов (например, алгоритм унификации типов Хиндли-Милнера). TAPL.
CS>Вопросы: CS>1) Что сделает думатель если увидит скажем такое: CS> hash[key] = flag? 1: "string";
В O`Caml алгоритм унификации (выведения типов) выдаст ошибку.
CS>2) C intellisense как я понимаю такой вывод типов дружить не будет? CS> Т.к. типы становятся известны только после построения syntax tree всей программы.
Во-первых, необязательно всей. Незнаю как в Nemerle, но в O'Caml можно давать явные аннотации типов. Во-вторых, IntelliSense может подсказывать те конструкции при введении которых алгоритм унификации выдает не пустое множество решений (т.е унификация типов возможна).
CS>И философическая часть:
CS>Зачем в принципе нужен такой выводитель типов? CS>Какие задачи он призван решить или облегчить их решение?
Проще писать программу (можно не задумываться о типах там, где это не нужно), компактнее код.
CS>Какие есть средства "детерминизаци": "я хотел сказать А а думатель придумал Б".
Аннотации типов, естественно. Где типы важны для тебя — ставишь аннотации. Где не важны — не ставишь и, соответственно, не ошибаешься в указании типа
CS>Личное замечание: CS>Такая недетерминированность в C++ является источником очень неприятных и дурных ошибок. CS>Один раз очень долго искал в чем проблема. Оказалось в наличии двух конструкторов у CS>объекта: cls(int n) и cls(bool b). (или что-то подобное — не помню) CS>Я имел ввиду одно а думатель молча выводил другой тип... Причем разные думатели CS>(компиляторы) думали по разному.
Во-первых, это немного другое. В твоем случае это больной subtyping и ad-hoc полиморфизм (aka overloading), насколько я понимаю. Но тоже имеет отношение к системе типов, а потому отслыаю опять к TAPL. Кстати, вот [http://lambda-the-ultimate.org/node/1113#comment-12147]тут[/url] (первое, что нашел в Google) есть мысль по этому поводу.
А во-вторых, вывод типов полностью детерминирован (это было бы странно, если бы он работал пользуясь "догадками" и "эвристиками", хотя не буду утверждать, что такого не бывает ). Открыв книгу, указанную выше, ты можешь найти описание алгоритма для ML-like языка.
Re[2]: Философический вопрос про автоматический вывод типов.
VD>expected int-, got string in computation branch: common super type of types [int, string] is a set of interfaces
VD>
VD>то есть, просто не даст так сделать.
Спасибо. Это я понял.
CS>>2) C intellisense как я понимаю такой вывод типов дружить не будет?
VD>А какая разница то кому делать вывод типов? Будет такой же вывод делать парсер интелисенса. VD>В первй строке он конечно ничего умного не предложит. Но в следующих уже предложет. VD>К тому же всегда можно задать тип при его создании. Только в отличии от большинства других языков однин раз. VD>
VD>def hash = Hashtable<string, int>();
VD>
VD>а не VD>Hashtable<string, int> hash = Hashtable<string, int>(); VD>как это сейчас происходит в С++ и C#.
Я не вижу принципиальной разницы в написании
Hashtable<string, int>() hash;
и
def hash = Hashtable<string, int>();
CS>> Т.к. типы становятся известны только после построения syntax tree всей программы.
VD>Они приципиально до этого не доступны. Любой интелисенст парсет все файлы проекта и крайне плохо относится к наличию ошибок в них.
Это очень дорогая операция парсить все файлы. Это не для GUI.
VD>Собственно пока типы ключей и значений имеют которкие имена, то замусоривания не так видно. Но когда это длинные типы темблее сами содержащие длиннющие параметры типов, то выходит довольно ужасно выглядящий код. Например, объявление той же хэш-таблицы может переноситься на две строки, чтобы влезнь в правила форматирования заставляющие переносить строки по 80 символов. C#: VD>
Несколько надуманный пример, имхо. Честно говоря такого безобразия я в своей практике не встречал.
Может из-за того что я ни stl ни boost не использую в быту?
CS>>И философическая часть:
CS>>Зачем в принципе нужен такой выводитель типов?
VD>Чтобы писать такой же краткий код как на динамически типизрованных языках, но при этом иметь все приемущества статически типизированных, в том числе быстрый код и интелисенс.
Еще раз с интеллисенсом не все так хорошо как ты написал. Запуск полномасштабного парсера (даже без кодогенерации)
на каждый введенный nmtoken это нереально.
На таких принципах можно и для скриптов intellisense строить. Что
кстати и сделано в VS. Там это правда работает для сугубо простых случаев.
CS>>Какие задачи он призван решить или облегчить их решение?
VD>Очистить код от лишних конструкций сделав его более кратким и понятным. При этом как бы не запрещается описывать типы более часто.
VD>Это как бы развитие идеии которую пытаются протлкнуть в следующую версию С++ (ключевое слово auto).
В принципе мотивация понятна.
Я просто думал что это решает некие принципиальные вещи.
Лично для меня явно определить тип всегда лучше — лишний checkpoint
который отлавливается в compiletime и сразу, а не в runtime.
Кстати Вальтер добавил в D auto т.е. такое вот работает:
auto i = 2+2;
Пока случая не представилось воспользоваться.
Re[3]: Философический вопрос про автоматический вывод типов.
Здравствуйте, eao197, Вы писали:
VD>>Не пишите на дурно спроектированных языках и не будете искать шибки очень долго.
E>Ага, а пока появятся хорошо спроектированные языки не программируйте ничего. E>И совсем уж философский вопрос: неужели за все время развития программирования еще не было создано ни одного нормально спроектированного языка? E>И что заставляет думать, что через некоторое время кажущийся нормально спроектированным язык не окажется объявленным дурно спроектированным?
Наблюдая плавное переливание Влада из C# в N# я тоже задаюсь этим вопросом.
И вообще нет идеальных языков для всего и вся.
Re[2]: Философический вопрос про автоматический вывод типов.
Здравствуйте, WFrag, Вы писали:
WF>Здравствуйте, c-smile, Вы писали:
WF>Disclaimer: Nemerle знаю только на основе предыдущих постов, сказанное ниже оносится скорее к O`Caml. Думаю, это не будет оффтопиком, так как проблема обсуждается с глобальной точки зрения
CS>>Не уверен. CS>>В условиях недетерминированного описания (типов в том числе) думатель CS>>будет вынужден "стелить соломку". CS>>Т.е. в принципе чем меньше информации имеет компилятор тем менее оптимальный CS>>код он строит. Более универсальный — да.
WF>В том-то и дело, что компилятор выводит недостающую информацию. Например, он может вывести что ты кладешь в массив только числа и сгенерировать код работы с массивом, оптимизированный под работу с числами. В то же время в Java ты вынужден либо писать свою специализацию, либо терять производительность на боксинге.
Еще раз мне представляется проблема несколько надуманной.
На Java я пишу немного в последнее время. А в C++ автоматический вывод типов
я из своей практики исключил. И лучше бы его там не было вообще.
WF>Вообще, почитай про реконструкцию типов (например, алгоритм унификации типов Хиндли-Милнера). TAPL.
Ага, спасибо. Но в другой жизни уже. В этой я чукча — писатель.
CS>>Вопросы: CS>>1) Что сделает думатель если увидит скажем такое: CS>> hash[key] = flag? 1: "string";
WF>В O`Caml алгоритм унификации (выведения типов) выдаст ошибку.
Почему? А если я так хочу и согласен на boxing например или на какой-нибудь variant?
CS>>2) C intellisense как я понимаю такой вывод типов дружить не будет? CS>> Т.к. типы становятся известны только после построения syntax tree всей программы.
WF>Во-первых, необязательно всей. Незнаю как в Nemerle, но в O'Caml можно давать явные аннотации типов. Во-вторых, IntelliSense может подсказывать те конструкции при введении которых алгоритм унификации выдает не пустое множество решений (т.е унификация типов возможна).
Проблема intellisense тут давеча обсуждалась а приложении к SELECT ... FROM.
Это оно как мне кажется, нет?
CS>>И философическая часть:
CS>>Зачем в принципе нужен такой выводитель типов? CS>>Какие задачи он призван решить или облегчить их решение?
WF>Проще писать программу (можно не задумываться о типах там, где это не нужно), компактнее код.
CS>>Какие есть средства "детерминизаци": "я хотел сказать А а думатель придумал Б".
WF>Аннотации типов, естественно. Где типы важны для тебя — ставишь аннотации. Где не важны — не ставишь и, соответственно, не ошибаешься в указании типа
"не ошибаешься в указании типа". Если я ошибусь мне компайлер скажет.
А в твоем случае скажет unittest. Который еще писать надо.
Но это так. Еще раз — мотивацию понимаю. Просто думал что это что-то принципиально новое позволяет делать...
Re[3]: Философический вопрос про автоматический вывод типов.
Здравствуйте, c-smile, Вы писали:
CS>Еще раз мне представляется проблема несколько надуманной. CS>На Java я пишу немного в последнее время. А в C++ автоматический вывод типов CS>я из своей практики исключил. И лучше бы его там не было вообще.
Интересно, как можно говорить о некоторой возможности если ты даже с ней не работал (впечатление такое сложилось)?
WF>>Вообще, почитай про реконструкцию типов (например, алгоритм унификации типов Хиндли-Милнера). TAPL.
CS>Ага, спасибо. Но в другой жизни уже. В этой я чукча — писатель.
..и даже не хочешь узнать, что это за фича и как она работает.
WF>>В O`Caml алгоритм унификации (выведения типов) выдаст ошибку.
CS>Почему? А если я так хочу и согласен на boxing например или на какой-нибудь variant?
В O`Caml disjoint union-ов нет. Но ничто не мешает использовать в данном случае joint union.
Если под "боксингом" ты имеешь ввиду полиморфизм (т.е когда в массиве хранится некий Object или т.н "Top"), то ситуация такая. (далее идут мои, возможно ошибочные, размышления). Вообще говоря, можно ввести тип Top, однако в силу статичности O`Caml его смысл несколько теряется (т.к ты все равно с этим типом потом ничего осмысленного не сделаешь).
CS>Проблема intellisense тут давеча обсуждалась а приложении к SELECT ... FROM. CS>Это оно как мне кажется, нет?
Не знаю, это все теоретические размышления. На самом деле нормальной подсказки для ML языков я действительно не видел (правда, особенно и не искал ). Может это и будет проблемой, может и нет.
WF>>Аннотации типов, естественно. Где типы важны для тебя — ставишь аннотации. Где не важны — не ставишь и, соответственно, не ошибаешься в указании типа
CS>"не ошибаешься в указании типа". Если я ошибусь мне компайлер скажет. CS>А в твоем случае скажет unittest. Который еще писать надо.
Нет. Тип выведется. И в худщем варианте, выведется более общий тип, чем ты указал бы.
CS>Но это так. Еще раз — мотивацию понимаю. Просто думал что это что-то принципиально новое позволяет делать...
Да, позволяет. Работать с очень сложными типами. Пример — монады (а еще лучше Arrows Хаскелля ). Посмотрел бы я на того маньяка, кто захочет везде явно типы указывать Ты указываешь типы для граничных случаев (там где ввод/вывод, например), а все остальные внутренние сложные типы выводятся автоматически.
Re[3]: Философический вопрос про автоматический вывод типов.
CS>Это очень дорогая операция парсить все файлы. Это не для GUI.
Ты видел resharper? Он не только парсит файлы, он производит куда более сложный анализ. Парсить файлы — единственный способ для нормального рефакторинга/intellisense. В Nemerle поддержка редакторов предпологается вообще с помощью встраивания компилятора(естественно не все его стадии, только парсинг и построение AST). Собственно какую-то раннюю версию этой библиотеки я видел в исходниках компилятора. Проблема со скоростью — не проблема на hi-end машинах(например vs2005 на других и работать толком не будет). Потом Nemerle и аналогичные языки рассчитаны на достаточно далекую перспективу, а закон Мура еще никто не отменял.
CS>Еще раз с интеллисенсом не все так хорошо как ты написал. Запуск полномасштабного парсера (даже без кодогенерации) CS>на каждый введенный nmtoken это нереально.
Это вполне реально и работает.
CS>Лично для меня явно определить тип всегда лучше — лишний checkpoint CS>который отлавливается в compiletime и сразу, а не в runtime.
Никто не говорит, что этого делать нельзя. Более того даже в Nemerle это иногда делать необходимо. Но если этого не делать в тех случаях, когда это можно, то ошибки всплывут именно в compiletime, а не в runtime. И я не видел еще ни одного случая, когда бы это было не так.
Re[3]: Философический вопрос про автоматический вывод типов.
Нет. Как и using. Но это тот же лишний код. Зачем он если без него очень даже неплохо получается?
E>После программирования с RubyOnRails я думаю, что это не есть хорошо.
Я тебе уже не раз говорил, что Руби хотя вещь и красивая, но далекая от совершенства. Не нужно по ней судить о других языках.
E> Там так же классы-модели возвращают какие-то объекты, которые затем используются формами для отображения информации. И очень скоро без явного декларирования типов возвращаемых объектов напрочь забываешь, что окуда возвращается и как с этим можно работать. А уж поддерживать целостность всего этого дела можно только за счет обилия unit-тестов. Приведенный тобой пример очень похож на эту ситуацию.
Хм. Нэмерл выводит типы. Это всеравно что вписывать их явно. Так что ошибок быть не может. Язык статически типизированный!
Когда я тебе говорил о том, что проблема Руби отсутствие статической типизации ты мне все время возражал и говрил, что все ОК, плюс есть юнит-тесты и т.п. Сейчас же сам себе возражаешь.
Сдается мне, что ты пытайся отстоять свое даже вопреки здравой логике.
Так вот схожесть Руби и Нэмерла ты правильно подметил. На обоих языках можно писать максимально кратко. Но ты упорно не хочешь понять, что отсутствие деклараций типов в этих языках достигается разными средствами. В Нэмерле — умом компилятора, а в Руби динамической типизацией.
VD>>Не пишите на дурно спроектированных языках и не будете искать шибки очень долго.
E>Ага, а пока появятся хорошо спроектированные языки не программируйте ничего.
Яве уже сто лет. C# 4. Так что самое время возиться с С++ и Руби. Их тандем позволяет сделть систему и запутаннее, и медленнее, и бажливее. Шучу конечно, но в каждой шутке...
E>И совсем уж философский вопрос: неужели за все время развития программирования еще не было создано ни одного нормально спроектированного языка?
Почти все новые языки лучше своих прототипов. С++ несравненно лучше С. C# ле... в общемя, ф промолчу.
Лучше скажу, что сейчас новые языки пытаются стать лучше чем свои предшественники и рано или поздно у кого-то это получится.
Бывает, конечно, что новый язык впитывает кучу проблем и становится хуже прототипов. Но бывает же и наоборот.
Нэмерл впитал в себя:
1. Антиграблевость и простоту применения C#.
2. Заимствовал лучшие вещи из синтаксиса С, Паскаля, C#, Питона и других.
3. Идеи функционального подхода из ML-клонов.
4. Макросы из клонов Лиспа.
Он поддерживает все известные мне парадигмы программирования. Причем делает это не случайно как С++ и не ограничено как многие языки, а намеренно и от того вроде как полно и не противоречиво.
На нем можно писать в функциональном стиле не хуже чем на МЛ. Он поддерживает и линивость, и одновременно yeld в чтиле Руби/Питона/Шарпа. Он намеренно поддерживает метапрограммирование. Причем делает это великолепно. Фнуциональные возможности упрощают создание макросов, а от того делают их применение доступнее для людей. Код в императивном стиле на нем мало отличим от такого же кода на C# только выглядит более кратно и если что нет проблем воспользоваться любой другой парадигмой.
Забавно, но когда я описывал, здесь неподалеку, то, что я хотел бы включить в C#, то описал большинство того, что уже есть в Нэмерле.
E>И что заставляет думать, что через некоторое время кажущийся нормально спроектированным язык не окажется объявленным дурно спроектированным?
А ничего и не заставляет. Когда я познакомился с С, я вообще ничего другого не видел, но по словам отца — это был самый современный и развитой язык на тот момент. Когда я задолбался тужится писать ОО-код на С и познакомился с С++ я был в щенячьем восторге от того как логично и красиво в нем реализован ООП! Шаблоны в те времена были еще далекти от того чем они стали сейчас. Мне они были не нужны. Но я все равно радовался как ребенок (возможно, потому что тогда я действительно был тогда почти ребенком и гомонов было через край) от раскрывшихся возможностей и невиданной мной до этого простотой.
Потом я радовался новым версиям С++ с шаблонами и вновь появившейся простоте. Тогда я еще не в силах был понять всю ущербность дизайна С++, а о многих концепциях вообще не знал.
Потом я радовался, изучая КОМ, так как получил в свои руки небывалую мощь компонетных технологий!
Далее я радовался, изучая Васик и Дельфи. Их компонентные модели были очень и очень впечатляющие. А визуальные дизайнеры форм в купе с компонентным подходом ускоряли создание ГУИ на порядки. Я вспоминал как недели убивал на приличный оконный интерфейс на С и с удовольствием наблюдал как намного более мощный интерфейс лепится из компонентов прямо на глазах.
Потом я примерно с твоим скепсисом наблюдал за появлением Явы. Я произвел пару тестов и выяснил, что скорость получаемого кода в десятки раз меньше чем у аналогичного на С++. Я не заметил в Яве мощной компонентной модели и заметил, что то на что ее нацеливают (создание апплетов для Web-а) не входит в круг моих интересов. Так я проморгал первую интересную вещь.
Я делал КОМ-компоненты на С++ и использовал их из Васика получая тем самым преимущества от гибкости С++ и скорости разработки Васика. Подспудно я понимал, что Дельфи в некотором роде является комплексной альтернативой, но количество багов в Дельфи, откровенно слабые библиотеки не связанные с ГУИ, и отсутствие некоторых вкусностей С++ заставили меня выбрать связку С++/Васик.
Далее я наблюдал за дотнетом. В дотнете я обнаружил C# который позволил мне делать все то что я раньше мог делать только на связке С++/Васик/КОМ на одном языке получая при этом куда более простые и безопасные решения. Дотнет и Шарп дали мне еще один повод для радости. Код на Шарпе был реально проще, а значит я смог делать куда больше за то же время.
Ранее я очень страдал, что даже самая крутая хреновина улучшающая комплит в VC++ 6,0 (забыл как ее помню только что фирма была про помидоры "Тамата") постоянно ошибалась на шаблонах С++ и не давала писать дефствительно быстро. Этих проблем не было на Васике, где комплит работает почти изумительно, но гибкость и производительность Васика была ниже плинтуса. В Шарпе же комплит стал еще круче чем в Васик, а язык очень даже сопоставим по гибкости с любимыми до этого плюсами. Вроде бы по отдельности все что было в Шарпе и дотнете я мог получить и ранее, но вместе этого не было нигде.
Так же стоит отметить и библиотеки. 80, если не больше, процентов времени работы на С++ мы уделяли разработке собственных библиотек. С Интернетом тогда было хреново, Буста еще не было, про разные Асе или КуТи мы просто не слышали. Все приходилось делать с нуля. Опыт применения чужого кода оказался горьким, так как в нем были баги, чужие баги связанные с нарушением типобезопасности искать в С++ ой как не просто. В общем, мы быстро приняли для сбея правило — все что используется должно быть написано нами и лежать в исходном коде! Так вот на Шарпе я впервые ощутил, что есть огромная полезная библиотека код которой не страшно использовать. Так же оказалось, что чужой код написанный на Шарпе не так страшно применять в своем коде. Ведь в нем невозможны ошибки связанные с типами и почти все грабли С++, а логические ошибки довольно легко обнаруживаются и устраняются или обходятся во время эксплуатации.
Еще одним достоинством, которое я не смог оценить сразу, но оценил потом было то, что дотнетные библиотеки легко декомпилировались. Сначало Анакрино, а потом и Рефлектор открыли для меня одну важную мысль. Отлаживаться имея возможность быстро найти код используемых библиотек — это очень большое преимущество. Используя С++ я не мог заглянуть в кишки КОМ-а и мы море времени проводили из-за того, что не верно поняли документацию, или в следствии того, что в недоступном коде был баг, а возможно просто что-то прощелкали, мы тратили тоже не мало времени. Теперь же, когда у меня в руках Рефлектор, я быстро могу найти нужный мне библиотечный метод и поглядеть его логику. Сделав это я могу понять в чем я был не прав или найти ошибку в чужом коде. Только недавно нашел ошибку в обертке над ListView. Я очень долго бы просидел над ее поиском если бы я не смог поглядеть ее код. Тут же, я быстро ее обнаружил, и смог понять, как ее легко обойти. На С++ даже имея исходники я не мог так быстро найти нужные мне места, а так как в большинстве случаев и исходников небыло, то был вообще каюк. Я конечно знаю, что сейчас есть разные Доксигены, но тогда их не было! Да и без исходников обходится.
ФЯ пожалуй первая вещь которую я оценил теоретически. Оказалось, что я и раньше частенько писал в ФЯ стиле на ИЯ даже не догадываясь об этом. Откровенно говоря, рассказы о том, что большинство ошибок в программах из-за модифицирующего присвоения меня не вдохновили. Ну, нет у меня в программах таких ошибок. Или почти нет. Но может быть я опять просто не оценил очередной виток облегчения. А вот декларативность записи я оценил. Я заметил, что декларативность можно достигать из без применения ФЯ и она всегда дает хороший результат. Забавно оказалось и то, что любимый мною SQL оказался тоже вроде как разновидностью ФЯ. По крайней мере, он был точно декларативным языком и видимо по этому он мне так нравился.
С SQL я тоже познакомился забавнейшим образом. Обучаясь программировать на С/С++ я быстро понял, что для решения стоящих передо мной задач мне нужно нечто обеспечивающее простую манипуляцию данными. Причем так чтобы этих могло быть много. В общем, мне была нужна СУБД. То что это называется БД, мен сказали добрые люди. Один знакомый отца дал мне библиотеку позволяющую манипулировать БД типа DBASE на С/С++ (вроде называлась CODBASE). Я довольно быстро научился вытягивать данные табличек, но как вынуть только их нужную часть, да еще и отсортированную нужным образом сразу не просек. После долгого копания я понял, что нужно использовать странные сущности вроде индексов и т.п. Короче нужно делать кучу работы о которой я не подозревал и которая по большому счету мне и на фиг не уперлась.
Я забросил эту идея и впервые решил, что нужно сделать свой велосипед. Такой движок, чтобы не нужно было делать лишних телодвижений для управления данными. Быстро поняв, что задача сложная, а мне нужно пока что куда менее универсальное решение я обошелся просто файлами.
Через некоторое время я познакомился с ребятами из маленькой конторы которые рассказали мне про то что есть такие штуки как SQL и SQL-серверы. А так же относительно дешевый SQL-сервер Gupta SqlBase и невероятное, по тем временам, визульаное средство SqlWindows. Это было время кода Васика или вообще небыл, или был Васик 1.0 настолько убогий, что с SqlWindows он никак не мог сравниться. Чуть спустя появилась NT и Эксес. Я быстро осознал, что будущее за серверами приложений, SQL-лем и средствами быстрой разработки вроде SqlWindows. Кстати, Дельфи появилась точно позже.
В общем, я чуть отвлекся... Познакомившись с ФЯ я обнаружил, что в них, таких не понятных и таких непривычных есть нечто привлекательное. Они действительно обладают чертами декларативности и код на них может быть значительно более кратким чем привычный мне императивный. Но та неинтуитивнасть которая присутствовала в функциональных примерах, дурацкая манера разворачивать смысл программы по сравнению с естественными языками и совершенно дурацкая манера называть переменные и функции так чтобы никто не догадался (с) операция "Ы", сильно смущали меня.
Так же смущало меня и то, что ФЯ пропагонидируют стиль явно не дружащий с высокой производительность. А та фанатичность с которой апологеты ФЯ борются против любых проявлений "императивщины" и так кривизна появляющаяся когда на традиционных ФЯ начинают писать в императивном стиле сильно смутили меня.
Но главное я осознал — это то, что и ФЯ есть рациональное зерно. А еще "более главное" , то что за декларативностью будущее! Пусть полный отказ от императивных конструкций — это утопия. И пусть пока еще нет ФЯ который я счел бы удобным для сбея, но в этом что-то есть!
Кстати, больше всего меня смущало в ФЯ, то что их принципы входят в противоречие с принципами ООП. А ООП я и сейчас считаю одним из самых мощных инструментов для решения сложных задач. Не, ну, правда, как идея о том, что "модификация состояния — это зло", может сочетаться с идеей, что "объекты имеют свое состояние модифицируемое посредством методов"? Слова вроде "так при модификации могут порождаться новые объекты" выглядят совсем не убедительно. Однако я же не фанатик ФЯ? Так почему я должен принимать идею о том, что модификация состояния — это зло? Темболее, что декларативность достигаемая в ФЯ отнюдь не заключена в немодифицируемости. Она скорее в другом. Она в том, что функции являются первоклассными сущностями, и в том, что с их помощью можно делать гибкую функциональную декомпозицию. В общем, функциональный взгляд на мир дает еще одно измерение.
Если подумать, то чем так хвастаются апологеты ФЯ:
1. Функции как первоклассные сущности.
2. Списки как первоклассные сущности (иными словами упрощенная работа со списками).
3. Использование рекурсии в программах.
4. Сопоставление с образцом.
5. Метапрограммирование.
Ничего не забыл?
Не являются по существу атрибутами ФЯ или функционального подхода в целом. Возможно они родились в среде ФЯ и красиво интегрированы в ФЯ, но это всего лишь стечение обстоятельств!
Так что без проблем можно создать гибридный подход позволяющий выбирать парадигму требуемую для решения текущей задачи.
Так вот Скала и Нэмерл ближе всех подошли к тому, что мне кажется перспективным на сегодня.
И пусть, не многие еще могут понять мощь которую несут эти языки. Пусть на их пути стоят такие непреодолимые препоны как:
1. Фанатизм приверженцев тех или иных имеющихся технологий.
2. Закостенелость мышления большинства.
3. Приверженность людей к своим привычкам. (О сколько раз я наблюдал, как люди понимают, что печатать методом слепой десятипальцовой печати намного эффективнее, но по тыркавшись бросающих попытки научиться ему).
4. Мощь гигантов индустрии вроде MS, Sun или IBM не до конца осознавших куда нужно двигаться. Причем, похоже, что они осознают куда нужно двигаться, но боятся, что факторы идущие в этом списке выше приведут их усилия в тупик.
Но движение в нужном направлении видно. Гиганты индустрии во всю развивают декларативные подходы. Они встраивают в свои модерновые языки декларативные конструкции (C# 1/2, Ява 1.5). Они поддерживают исследования в области ЯП. Они занимаются визуальными дизайнерами и ищут пути внедрения DSL-подхода в реальную жизнь. В общем, они двигаются вперед. Хотя, возможно, и не так быстро как хотелось бы.
Что же касается до того что в будущем могут появиться подходы, которые мы пока не видим, или в которых мы пока не уловили конструктивного зерна, так я этого не боюсь. Собственно для этого я и рассказывал все вышесказанное. Это будет всего лишь следующий шаг. Я только "за" новые шаги. И чем более радикально этот шаг упростит нашу жизнь, тем лучше.
Чудесь не бывает. Это я понял еще в жизни. И если кто-то сильно что-то хвалит не объясняя на чем базируются эти преимущества, то скорее всего это фигня. Из этого же правила следует и то, что супер-панацей нет. А есть только грамотный баланс. Так что моя задача сопоставить плюсы с минусами и выбрать то у чего этот самый баланс близок к оптимальному для меня.
ЗЫ
Многие считают меня фанатиком. Но они ошибаются. Я в каком-то смысле продажная шкура. Если я вижу что-то по совокупности характеристик лучшее чем то что мне нравилось до этого, то я легко бросаю старую игрушку и беру лучшее. Просто не так много вещей в мире которые действительно кумулятивно (по совокупности) лучше чем то, во что я играюсь сегодня. Возможно мне просто плохо объясняли, а возможно я просто не столь дальновидный. Но мне кажется дело все же не во мне. Я конечно люблю поспорить и увлекшись могу начать отстаивать и не верную позицию. Но выслушав аргументы и остыв я все же (по крайней мере хочется в это верить) способен оценить их и принять решение на основании логики, а не собственной вредности.
На сегодня я вижу перспективу за компонентными управляемыми средами вроде дотнета и Явы. За типобезопасностью, статической типизацией, декларативностью, метапрограммированием, и многим другим. И из всего что я вижу Нэмерле и Скала являются самыми перспективными вещами. Но я уже очень давно подсел на иглу под названием хорошая IDE (под которыми на сегодня я понимаю только два продукта VS, причем только 2005 или 2003 + ReSharper) и IDEA. Остальное не стоит даже обсуждения. Чуть-чуть сюда приблизился Эклипс. Но по многим характеристикам он уступает. В общем, без хорошей IDE моя производительность на C# значительно выше чем на супер пупер Нэмерле. Но я почти уверен, что со временем или C# впитает в себя все преимущества Нэмерла, или Нэмерле обзаведется поддержкой мощной IDE (для начала хватило бы хорошего комплита). Ну, или появится нечто лучше чем Шарп и Нэмерл вместе взятое обладающее офигительной IDE, а возможно и тем самым "чем-то новым о чем мы еще не знаем" и вот именно это и станет моим фаворитом на некоторое время.
А потом (если буду жив) я снова буду сидеть в форуме и бороться с закостенелыми фанатами устаревших технологий вроде C# 5.0 и Нэмерле 3.0 и они мне будут говорить, что я фанатик и вообще несдержанный идиот. Главное не влиться в стройные ряды рядов совсем экзотических извращений или в ряды старперов по духу защищающих пережитки прошлого.
Вот такая я бяка.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Философический вопрос про автоматический вывод типов.
Здравствуйте, VladD2, Вы писали:
VD>Хм. Нэмерл выводит типы. Это всеравно что вписывать их явно. Так что ошибок быть не может. Язык статически типизированный!
VD>Когда я тебе говорил о том, что проблема Руби отсутствие статической типизации ты мне все время возражал и говрил, что все ОК, плюс есть юнит-тесты и т.п. Сейчас же сам себе возражаешь.
VD>Сдается мне, что ты пытайся отстоять свое даже вопреки здравой логике.
нет принципиальной разницы. Без разглядывания подробностей реализации make_report нельзя сказать, что находится в Hash.
Только Nemerle будет давать по рукам во время компиляции (если будет явное нарущение, а то ведь он может и сам какие-то типы вывести). Это хорошо.
Есть! И приципиальная! В Нэмерле тип выражения известен во время компиляции со всеми вытекающими из этого проверками.
И вот еще что. Заметь! Ты сравнивашь скриптовый язык с языком который по всем параметрам кроме простоты или не уступает, или привосходит С++. А в простоте он его делает как катентка.
Не плохо, правда? Статически типизированный стрипт! Кстати, у Нэмерла есть нечто вроде интерпретатора.
E> Без разглядывания подробностей реализации make_report нельзя сказать, что находится в Hash.
Это в Руби нельзя. А в Нэмерле можно. Даже наоборот нельзя по другому.
E>Только Nemerle будет давать по рукам во время компиляции (если будет явное нарущение, а то ведь он может и сам какие-то типы вывести). Это хорошо.
Именно.
E>Но лучше, когда объявление метода будет вида: E>
Тебе уже раз 5 сказали, что в немерле вольности с типами допускаются только в рамках одного метода. Все глобальные сущьности, в том числе, методы, их параметры, свойства и поля обязаны обявляться явно. Сделано это именно в целях документирования, минимизации ошибок и ускорения компиляции. То есть весь код можно писать не обращая внимание на типы. А вот члены класса прийдется опиысывать полностью. И это правильно!
VD>>1. Антиграблевость и простоту применения C#.
E>Об этом сейчас я бы не стал судить. Макросы в Nemerle это отдельная и большая поляна для грабель.
Макросы писать не обязательно. И отлаженный макрос способен вызвать только те грабли которе ты сам лично туда зложил. Эдак и на C# можно граблей понавтыкать если, например, сделать неявных приведений к булеву типу у чего попало. Но люди же разумны.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Философический вопрос про автоматический вывод типов.
VD>>а не VD>>Hashtable<string, int> hash = Hashtable<string, int>(); VD>>как это сейчас происходит в С++ и C#.
CS>Я не вижу принципиальной разницы в написании
Принципиальная разница в том, чо мжно и без <string, int>, как ты мог заметить.
А так же в универсальности. def задает неизменяемую переменную которая может быть локальной функцией, ссылкой на тип...
VD>>Они приципиально до этого не доступны. Любой интелисенст парсет все файлы проекта и крайне плохо относится к наличию ошибок в них.
CS>Это очень дорогая операция парсить все файлы. Это не для GUI.
Я не виноват, что ты не занимался этим вопросом. Поверь на слово. Без прасинга всех файлов интелисенст не работает. Днугое дело, что никто не парсит все файлы на каждое нажатие клавиши на клаве. Конечно же полный парсино происходит при открытии проекта или его изменении извне. А при изменении содержимого функции по блокам отсекается изменившаяся функция и перепарсивается только ее содержимое.
CS>Несколько надуманный пример, имхо. Честно говоря такого безобразия я в своей практике не встречал.
А я встречал. Не раз приходилось делать юснги на используемые в хэш-таблицах типы. Ну, да в С++ "точек" чуть по меньше да и ООП там ен так часто по полной используют. Так что может эта проблема не так актуальная. Хотя точно сопсбствует более коротким, а стало быть менее информативным именам.
CS>Может из-за того что я ни stl ни boost не использую в быту?
Может.
CS>Еще раз с интеллисенсом не все так хорошо как ты написал.
Вывод типов не проблема для интелисенса. Вот макросы — длугое дело. Но вроде как работы над этим делом уже ведутся. Интелисенс делают прямо на базе компилятора.
CS> Запуск полномасштабного парсера (даже без кодогенерации) CS>на каждый введенный nmtoken это нереально.
Если его научить парсить отдельную функцию, то без проблем. И вообще, чем по-твоему отличается "полномасштабный парсер" от парсера для интелисенса? Это толко у С++ с этим проблемы в следствии кучи неоднозначностей и инклюдов.
CS>На таких принципах можно и для скриптов intellisense строить.
Нельзя. Вывод типов отустуствует. А без него не ясно что за тип имеет идентификатор. Если же можно сделать вывод типов, то не ясно зачем вообще нужна интерпретация и нинамическая типизация.
CS> Что CS>кстати и сделано в VS. Там это правда работает для сугубо простых случаев.
Если ты про ASP (то что было до дотнета) и про старую студию, то там как раз и использовался вывод типа. Правда так как скрипты позвляли это делать плохо, то и результат был очень ограниченным. Тут же гарантируется 100%-ный вывод типов.
CS>В принципе мотивация понятна. CS>Я просто думал что это решает некие принципиальные вещи.
А разве краткость кода как в Питоне и Руби при типизации строже чем в С++ — это не принципиальное решение?
CS>Лично для меня явно определить тип всегда лучше — лишний checkpoint CS>который отлавливается в compiletime и сразу, а не в runtime.
Дык всто тоже самое, только делать ничего не надо. Ести ты привык декларироваь типы, то продолжай это делать. Компилятору работы поубавится. А елси ты привык к скриптам, то получишь всо тоже самое, только без жертв всвязанных с динамической типизацией.
CS>Кстати Вальтер добавил в D auto т.е. такое вот работает: CS>auto i = 2+2;
Такое и в C# скоро появится. Согласись Нэмерл пошел сильно дальше.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Философический вопрос про автоматический вывод типов.
Здравствуйте, VladD2, Вы писали:
VD>И вот еще что. Заметь! Ты сравнивашь скриптовый язык с языком который по всем параметрам кроме простоты или не уступает, или привосходит С++. А в простоте он его делает как катентка.
Ты так уверен? Сколько кода ты написал на Nemerle чтобы об этом судить?
E>>Об этом сейчас я бы не стал судить. Макросы в Nemerle это отдельная и большая поляна для грабель.
VD>Макросы писать не обязательно. И отлаженный макрос способен вызвать только те грабли которе ты сам лично туда зложил.
Классная фраза. Эдак про што угодно сказать можно.
Макросы отличаются от обычного кода тем, когда и как они запускаются. Можно ли, например, их отладочными печатями проверять?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Философический вопрос про автоматический вывод типов.
Здравствуйте, VladD2, Вы писали:
VD>ЗЫ
VD>Многие считают меня фанатиком. Но они ошибаются. Я в каком-то смысле продажная шкура. Если я вижу что-то по совокупности характеристик лучшее чем то что мне нравилось до этого, то я легко бросаю старую игрушку и беру лучшее. Просто не так много вещей в мире которые действительно кумулятивно (по совокупности) лучше чем то, во что я играюсь сегодня. Возможно мне просто плохо объясняли, а возможно я просто не столь дальновидный. Но мне кажется дело все же не во мне. Я конечно люблю поспорить и увлекшись могу начать отстаивать и не верную позицию. Но выслушав аргументы и остыв я все же (по крайней мере хочется в это верить) способен оценить их и принять решение на основании логики, а не собственной вредности.
По поводу твоего красочного жизнеописания хотелось бы уточнить два вопроса:
1. У тебя вообще образование связано с программированием? Или же ты в большей степени самоучка?
2. Ты так с легкостью переходил с одной технологии на другую... А как быть с проектами, которые развивались в рамках какой-нибудь технологии в течении нескольких лет?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.