Здравствуйте, eao197, Вы писали:
E>Так вот интересно выслушать соображения о том, в каких случаях выгодно писать internal DSL (здесь уже как раз можно затронуть вопросы предпочтения одного языка другому в конкретных условиях), а в каких таки лучше предпочесть external DSL. Соответственно, узнать, что за цену придется платить в этом случае.
Так заведи соответствующую дискуссию Что ты, собственно, и сделал ниже.
O>>А за разворачивание чересчур уж бурной дискуссии я ответственности не несу — я всего лишь защищался
E>Оправдания -- признак признания вины
Хорошо, что ты не в суде работаешь
E>Nemerle как раз в тему (я сам первым его название здесь упомянул ), но не в качестве противопоставления Nemerle rulez forever!, а C++ must die! E>Было бы интересно как раз примеры DSL на Nemerle видеть. Скажем о примере с размерностями. Для меня в нем самым интересным является как раз небольшой фрагмент с описанием одних величин через другие. Вот это выглядит интересно. Имхо, это то, что действительно можно считать удачным декларативным DSL.
Это и дальше — +1.
А насчёт external DSL... боюсь, что их писать тяжелее, чем internal. Т.е. я уверен, что тяжелее, но боюсь, что намного. Я, например, из статьи так и не понял, насколько сложно с помощью описанного инструмента создать собственный DSL. Т.е., например, прикрутить DSL, подобный использованному мной, к C++ имхо будет непросто — прийдётся писать как минимум файл грамматики для какого-то парсера вроде Coco/R или ANTLR вместе с кодом, который по AST будет как-то генерить C++-код. Вот мне в итоге непонятно, насколько это будет проще с использованием MPS... примеры из статьи ничего мне не показали в этом плане.
что такое? Что это за (1)? Передача липового параметра в конструктор переменной единственный смысл которой задать выражению тип? И где тут аналогичный код? У меня тип задаётся слева. Никакого аналогичного кода я пока не увидел.
O>Это я к тому, что тут шаблоны C++ не спасают и на Nemerle присутствует лучшее решение
Здравствуйте, Oyster, Вы писали:
O>Сравниваются определение типа и определение типа. Жаль, что ты это не понял до этого момента.
Влад назвал это оператором приведения типа.
A>>Во-вторых, мой способ гибче, потому что я не принимаю Си за точку отсчёта и ничто не мешает написать A>>
Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.
A>>В-третьих, новые типы определяются настолько редко, что затратами на их определение, тем более конкретизацию шаблона, можно пренебречь.
O> Отличная отмазка
У тебя есть данные, что новые типы определяются так же часто как используются?
O>Кстати, сам автор исходной библиотеки на C++ признаёт, что такое решение коряво
Здравствуйте, adontz, Вы писали:
A>Ой да ладно. Вот это
value[Time / (Length ^ 2)](1)
что такое? Что это за (1)? Передача липового параметра в конструктор переменной единственный смысл которой задать выражению тип? И где тут аналогичный код? У меня тип задаётся слева. Никакого аналогичного кода я пока не увидел.
. Доволен?
O>>Это я к тому, что тут шаблоны C++ не спасают и на Nemerle присутствует лучшее решение
A>Вставлять надо туда, где написано "?что тут писать?". а твоё решение как выглядит?
Здравствуйте, adontz, Вы писали:
A>Влад назвал это оператором приведения типа.
Ты бы прочитал про мою библиотеку для начала. Кстати, где это Влад целую строку моего DSL назвал оператором приведения типа? Он говорил чисто про [ kg ], что преобразуется в унарный оператор. В целом же строка задаёт орт массы в системе СГС с коэффициентом нормализации.
A>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.
Отлично. Но кто тебе мешает вместо
def vol = 100 m * 10 cm
писать
def vol = Si.Mass(100) * Cgs.Mass(10)
???
A>У тебя есть данные, что новые типы определяются так же часто как используются?
У меня есть данные о том, что записанные с помощью шаблонов юниты тяжело "читать".
O>>Кстати, сам автор исходной библиотеки на C++ признаёт, что такое решение коряво
Здравствуйте, Oyster, Вы писали:
A>>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM. O>Кстати, в моей библиотеке никто тебе не мешает написать не
Это не гибкость. Гибкость это когда не надо переделывать библиотеку
Здравствуйте, adontz, Вы писали:
A>>>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM. O>>Кстати, в моей библиотеке никто тебе не мешает написать не
A>Это не гибкость. Гибкость это когда не надо переделывать библиотеку
Так библиотеку я и не трогаю я изменяю описание юнитов, которое не является частью библиотеки. Ты, кстати, тоже библиотеку трогал в таком случае.
В общем, к чему была эта фраза — не понял совершенно
Явно указывать типы это на самом деле очень полезно. А чтобы их указывать явно и гибко нужны нормальные шаблоны.
Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы? И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle?
Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись
Здравствуйте, Oyster, Вы писали:
O>Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы?
Да
O>И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle?
Выделеное вычёркиваем и я согласен.
O>Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись
Здравствуйте, adontz, Вы писали:
O>>Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы? A>Да
Ок
O>>И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle? A>Выделеное вычёркиваем и я согласен.
Почему вычёркиваем? Сваргать описание юнитов, подобное моему
, на C++, а потом вычеркнем. Или заявишь, что моё описание менее удобно?
O>>Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись A>А можно канфету в награду?
Я это написал не ради поиздеваться, а для того, чтобы ты задумался над тем, что, возможно, не стоить охаивать какую-либо технологию, не попробовав её, и безапеляционно размышлять о вещах, в которых не разбираешься.
Некрасиво писать про невозможность решение чего-либо на каком-либо языке (например, на Nemelre, в котором нет "нормальных шаблонов"), не попробовав (или спросив) об этом предварительно. Особенно если то, что написал, — ложь.
Здравствуйте, VladD2, Вы писали:
VD>С удовольствием помгу с языком и формулировками, но писать тебе, так как я скорее принадлежу той массе для которого все это далекий спор о высоких материях разбираться в которых сложно и неохота.
Хмм... это идея хорошая, не спорю. Думаю, я даже попробую, как будет время. Правда, тут есть один момент — моя лень Да и статьи я не то чтобы очень часто пишу (скорее, даже не пишу вообще).
В любом случае, спасибо за идею и уверенность в том, что статья найдёт своего издателя — с такими начальными условиями можно и попробовать А уж читателя она найдёт — в этом я точно уверен Пусть эта библиотека никому и не нужна, зато используется в ней много всего.
Здравствуйте, Oyster, Вы писали:
O>Хмм... это идея хорошая, не спорю. Думаю, я даже попробую, как будет время. Правда, тут есть один момент — моя лень Да и статьи я не то чтобы очень часто пишу (скорее, даже не пишу вообще).
Лень говоришь? Значит создавать такой объемный код не лень, а описать его лень? Нда...
С написанием статьи я помогу. Это не проблема. Ты хоть как-то напиши, а я подправлю/допишу.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Лень говоришь? Значит создавать такой объемный код не лень, а описать его лень? Нда...
То ж другое дело Доступно объяснить другим тяжелее, чем написать, естественно.
VD>С написанием статьи я помогу. Это не проблема. Ты хоть как-то напиши, а я подправлю/допишу.
Здравствуйте, Oyster, Вы писали:
O>А насчёт external DSL... боюсь, что их писать тяжелее, чем internal. Т.е. я уверен, что тяжелее, но боюсь, что намного.
Все зависит от того, что за DSL мы хотим получить. Могу говорить исходя только из собственного опыта. Когда-то давно, в 2000 году был у меня опыт создания external DSL для вот этого инструмента
Это все. Определение C++ класса и его реализация генерировалась компилятором этого DSL. Можно сравнить с тем примером, который приведен в статье
Но у external DSL было несколько недостатков.
— диагностика ошибок времени компиляции сгенерированного C++ кода. Хоть в C++ код и вставлялись соответствующие инструкции #line, все равно сообщения были трехэтажные из-за хитрых имен классов и методов
— отладка. В общем-то не так уж и страшно, т.к. код события практически один в один совпадал с кодом, укзанным в описании события в {{...}}. Но вот найти это место в горах автосгенерированного кода...
— DSL был предназначен только для статических конфигураций, когда агенты не создаются и не удаляются в процессе работы динамически (сказалась заточенность под АСУТП задачи, где эта ситуация -- обычное дело).
Самый большой недостаток external DSL -- это то, что это был собственный язык, который нуждался в собственном парсере и процессоре. Поэтому при реинкарнировании этого проекта в виде SObjectizer я очень серьезно думал, имеет ли смысл иметь DSL для описания агентов и их классов. В результате, из-за хронического недостатка времени было решено, что на реализацию транслятора нет ресурсов. Действительно, internal DSL на макросах C++ был сделан всего за пару дней. А первоначальный вариант транслятора показанного выше языка с использованием yacc разрабатывался несколько недель. Хотя основная трудоемкость была не в самом синтаксисе языка, сколько в создании корректного и полного кодогенератора.
Тем не менее, при наличии соответствующих ресурсов и/или упрощающих дело инструментов external DSL может быть очень удобным. Из-за того, что:
— external DSL может быть нейтральным по отношению к целевому языку. Например, IDL, из которого может генерироваться код для C++, Java, C#, Smalltalk и т.д.;
— external DSL может быть очень выразительным и не содержать синтаксического оверхеда, который проникает в internal DSL из-за особенностей host-языка. Скажем, в Ruby для DSL используются объекты Symbol (для записи которых приходится использовать нотацию :identifier, хотя лидирующее двоеточие легко пропустить), объекты Hash (при использовании которых приходится использовать нотацию key => value, хотя '=>' в ряде случаев желательно было бы опускать), жестко заданный порядок следования аргументов (хотя в некоторых случаях было бы желательно иметь возможность какой-то аргумент опустить) или же оформлять составные аргументы в виде дополнительных Array или Hash;
— external DSL могут позволять получать абстрактное представление описания (что-то вроде AST или какой-нибудь прикладной модели данных). Причем для разных задач можно получать разные модели. Скажем для статического анализа корректности связей между объектами -- одну модель, для рефакторинга -- другую, для построения документации -- третью. В случае internal DSL получение таких моделей может быть сильно затруднено;
— external DSL могут не иметь проблем при интеграции в один проект нескольких DSL. Например, просто из-за того, что в рамках одного описания нельзя будет смешивать несколько DSL Либо же наоборот, DSL позволяет вставлять в себя вставки "непрозрачного" для него кода, который сохраняется на выходе. Что делает возможным организацию pipeline DSL-преобразований. Скажем, из одного DSL получается cpp-файл, который подается на вход следующему транслятору DSL, на выходе которого следующий cpp-файл и т.д. Хоть и звучит это сложно, но вполне возможно. Например, вот здесь
я приводил пример external DSL, который генерирует C++ код, содержащий еще один DSL внутри -- комментарии в соответствии с правилами Doxygen-а. А это делает возможным сгенерировать по результирующему C++ коду Reference Manual;
— external DSL может позволять скрывать исходные тексты от клиента/заказчика в некоторых случаях. Например, для решения какой-то прикладной задачи мы используем external DSL и наши собственные, внутренние инструменты для его обработки. На выходе получаем набор исходных текстов для target-языка, по которым нельзя восстановить исходный DSL. Заказчику передается уже сгенерированный код, но не DSL-тексты. В результате мы можем иметь высокоэффективный внутренний инструмент, который мы не обязаны отдавать кому-либо даже при передаче всех исходников прикладной системы заказчику. Для которых языков программирования (для того же Ruby) сокрытие internal DSL от заказчика может быть просто не возможно.
Может быть есть и еще какие-то бенефиты, я перечислил только то, что сам с ходу вспомнил.
В общем, если для поддержки external DSL есть необходимые ресурсы/специалисты/инструменты, то external DSL в некоторых случаях могут быть весьма удобнее internal DSL. Не могу сказать, что это за случаи. Есть подозрение, что когда требуется описание нетривиальной предметной области или же одновременная поддержка нескольких target-языков.
А вообще, это нужно на месте, в зависимости от конкретной задачи, конкретной команды и степени самоуверенности конкретного архитектора DSL принимать решение
Одно для меня очевидно: internal DSL -- это, по сути, еще один способ оформления API (т.е. это больше Domain Specific language). А вот external DSL -- это уже создание отдельного языка (т.е. это больше Domain Specific Language).
O>Я, например, из статьи так и не понял, насколько сложно с помощью описанного инструмента создать собственный DSL. Т.е., например, прикрутить DSL, подобный использованному мной, к C++ имхо будет непросто — прийдётся писать как минимум файл грамматики для какого-то парсера вроде Coco/R или ANTLR вместе с кодом, который по AST будет как-то генерить C++-код. Вот мне в итоге непонятно, насколько это будет проще с использованием MPS... примеры из статьи ничего мне не показали в этом плане.
Да статья вообще производит очень скучное представление. И примеры в ней какие-то невнятные (на скриншотах). Да и оттенок маркетинга очень сильно ощущается.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Oyster, Вы писали:
O>Да и те, другие, вопросы, тоже обсуждаются. Разговор ведь пошёл о Nemerle потому, что появилась идея, что всё это нагромождение из тулзов, предложенное товарищем из JetBrains, возможно, не нужно, а достаточно языка, который позволяет посать обработчики любых DSL на себе.
Именно. Кто-то тоже самое сказал о Руби. И заметь их не нразвали фанатами.
O>Да, Nemerle гибок, но недостаточно для создания любого внешнего (в терминах Фаулера) DSL. Да и возможностей рефакторинга у него ноль на данный момент... Но это не означает, что в этой теме Nemerle лишний на 100%.
Глупость сказал. Создавать внешний ДСЛ можно на любом языке. Темболее на функциональном, так как они просто заточены на парсинг и генерацию.
O>А за разворачивание чересчур уж бурной дискуссии я ответственности не несу — я всего лишь защищался
Дисскуссия развернулась в основном с Адонцом. При этом она идет в общем-то не вокруг того плох Немерле или нет, а вокур того оправдан ли подход основанный на ДСЛ-ях. Естественно что в качесте примера приводится опыт из того языка который лучше всего подходит для ДСЛ-естроителства с нашей точки зрения. Зверек, как я понимаю, соглашаясь со мной в качестве языка для создания подразумевал использование Руби.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.