Здравствуйте, metaprogrammer, Вы писали: M> В качестве примера задачи, где введённые при раскрытии макры биндинги нельзя переименовывать — любой pattern matching.
А они и не переименовываются. Если ты биндишь к пришедшему в макрос извне идентификатору — все ок.
Mr.Cat wrote:
> Теперь твоя очередь рассказывать, чем cl лучше схемы.
Ну я -то схемы не знаю толком, чтобы сравнивать.
CL -- промышленно применимый язык. Он готов для разработки.
Со схемой в этом отношении -- я не могу дать гарантий.
Здравствуйте, Mr.Cat, Вы писали:
M>> В качестве примера задачи, где введённые при раскрытии макры биндинги нельзя переименовывать — любой pattern matching. MC>А они и не переименовываются. Если ты биндишь к пришедшему в макрос извне идентификатору — все ок.
Тут создаются новые биндинги для x и y, и если бы тут была гигиена, то она бы защитила от внутреннего переопределения (do-something x y), в результате чего получился бы конфуз.
Не, гигиена — штука запредельно бесполезная. Вреда от неё полно — ограничения на возможности метапрограммирования, сложная и потенциально глюкоёмкая семантика, а вот пользы — ни-ка-кой. Совершенно никакой.
И кстати о гигиенах и прочей фигне. Вот этот код ни в Ypsilon, ни в PLT не работает:
И не работает он по вполне понятным причинам. Что делает вообще хоть немного сложное метапрограммирование в Схемах без define-macro просто невозможным. Те, кто любит кричать за гигиену, всегда приводят в пример только всякую чушь — очередную макру let или там while. А макры — они вовсе не для того нужны, чтоб такие примитивные конструкции в язык добавлять, у них намного более широкая область применения.
Ещё кстати интересная неоднозначность — далеко не все Схемы понимают (begin (define ...) (define-macro ...) ...) в топлевеле. Соответственно, если одна макра не может раскрыться в несколько топлевел-определений, то это тоже сразу делает метапрограммирование в таком языке убогим и ни к чему полезному не пригодным.
Ещё одна гадость — невозможность передачи контекста между разными макрами. Простейшее (хоть и малость хаковатое) решение — это возможность контроля за порядком раскрытия макроопределений. В большинстве Схем тоже нереализуемо.
В общем, для серьёзного метапрограммирования голый R6RS не годится (про убогий R5RS с его syntax-rules я и вовсе помолчу). Рулят только Схемы, где есть define-macro из коробки.
Аноним 585 wrote:
> CL — write only каша, где глазу не за что зацепиться. В схеме не только > сразу виден синтаксис DSL-а, который вводится макросами, но и сразу > видно как его расширять.
1) ты привёл ссылку на внутренний код SBCL, он вообще не предназначен для
чтения нормальными людьми. Это — грубо говоря, вообще не common lisp.
2) loop в CL обсуждать вообще бессмысленно, многие его не любят, им не пользуются.
3) думаю, всё остальное достаточно субъективно.
ЗЫ: прочитал топик до конца, нет, я больше сюда не пишу
Почему схема может быть лучше я тоже не понял. Я понял,
что не пойму, пока не изучу схему так же хорошо, как я знаю CL.
Спасибо всем.
Здравствуйте, Mr.Cat, Вы писали:
M>> Один метод с большим селектом — не загнётся, очень даже эффективно получается. Но динамически такой код генерить уже нельзя. MC>Почему нельзя динамически?
А как? Каждый раз при добавлении нового определения перекомпилировать всё? Так в .NET даже class GC отсутствует.
Здравствуйте, MasterZiv, Вы писали:
MZ>ЗЫ: прочитал топик до конца, нет, я больше сюда не пишу MZ>Почему схема может быть лучше я тоже не понял. Я понял, MZ>что не пойму, пока не изучу схему так же хорошо, как я знаю CL.
Мне хватает одного аргумента — семантика (функционального подмножества) Схемы ближе к лябмда-исчислению. Так что изучать не Схему надо, а лямбда-исчисление, чтоб понять претензии к CL.
А зачем так дизайнить макры? Надо чтобы писалось примерно так:
(let ((x the-other-x-value))
(match something ((tag x . y) (do-something x y))))
Тогда к x и y можно будет делать биндинг, видимый для do-something. Погляди match.scm.
M>И кстати о гигиенах и прочей фигне. Вот этот код ни в Ypsilon, ни в PLT не работает: M> http://pastebin.org/13682
Каюсь, прочитал довольно поверхностно, но тебе вроде бы всего-то и надо — разбить на пару модулей, не?
M>Ещё кстати интересная неоднозначность — далеко не все Схемы понимают (begin (define ...) (define-macro ...) ...) в топлевеле.
Вообще-то сплайс бегина чуть ли не в r5rs есть. В r6rs точно.
M>Ещё одна гадость — невозможность передачи контекста между разными макрами. Простейшее (хоть и малость хаковатое) решение — это возможность контроля за порядком раскрытия макроопределений. В большинстве Схем тоже нереализуемо.
Порядок в r6rs стандартизован. А как его контролируют с defmacro?
M>В общем, для серьёзного метапрограммирования голый R6RS не годится (про убогий R5RS с его syntax-rules я и вовсе помолчу). Рулят только Схемы, где есть define-macro из коробки.
Ну если серьезное метапрограммирование — это куча макросов, вводящих левые биндинги (пишешь ~x — биндишь к x, не понимаю смысла в этом), и все в одно файле — то да.
Здравствуйте, Mr.Cat, Вы писали:
MC>А зачем так дизайнить макры? Надо чтобы писалось примерно так:
(let ((x the-other-x-value))
(match something ((tag x . y) (do-something x y))))
MC>Тогда к x и y можно будет делать биндинг, видимый для do-something. Погляди match.scm.
Нет. Не надо. tag — константа. Как отделишь от биндингов? Такой убогий match не нужен — надо разделять биндинги и символы. Соответственно, содержимое символов приходится парсить. Это сразу многократно увеличивает возможности синтаксиса. Зачем себя ограничивать ради дебильной и в принципе бесполезной гигиены? Зачем делать язык сложнее и глючнее, когда можно сделать проще, мощнее и надёжнее? А ведь это простейший пример. Посмотри на ранее обсуждавшийся def:ast, или на Infix, и на генератор парсеров — везде есть смысл кодировать символы. Везде гигиена только навредила бы. А пользы от неё ровным счётом никакой, вообще.
MC>Каюсь, прочитал довольно поверхностно, но тебе вроде бы всего-то и надо — разбить на пару модулей, не?
Не не не. Мне надо определять и тут же использовать. Возможно — в коде, который тут же был из этой же макры получен. Иначе это не метапрограммирование, а убожество будет, ничем не лучше препроцессора в Си.
MC>Вообще-то сплайс бегина чуть ли не в r5rs есть. В r6rs точно.
Однако некоторые реализации его не понимают.
M>>Ещё одна гадость — невозможность передачи контекста между разными макрами. Простейшее (хоть и малость хаковатое) решение — это возможность контроля за порядком раскрытия макроопределений. В большинстве Схем тоже нереализуемо. MC>Порядок в r6rs стандартизован. А как его контролируют с defmacro?
В CL — тоже никак. Но тривиальное расширение к макросистеме позволяет решить эту проблему.
MC>Ну если серьезное метапрограммирование — это куча макросов, вводящих левые биндинги (пишешь ~x — биндишь к x, не понимаю смысла в этом), и все в одно файле — то да.
Серьёзное метапрограммирование — это реализация компилируемых eDSLей. Всяких, разных/ С гигиеной таких языков делать не получается:
Здравствуйте, metaprogrammer, Вы писали: M> Нет. Не надо. tag — константа. Как отделишь от биндингов? Такой убогий match не нужен — надо разделять биндинги и символы. Соответственно, содержимое символов приходится парсить.
Их можно матчить в syntax-rules. Просто указываешь в опредлении макры, что tag — не синтаксическая переменная, а должен встретиться такой символ.
M>Везде гигиена только навредила бы.
Вредит часто не гигиена, а неумение (нежелание) ее использовать. Паттерн-мачинг прекрасно реализуется с гигиеной. Инфиксный синтаксис навскидку тоже. Def:ast не смотрел.
M> Однако некоторые реализации его не понимают.
Не встречал. Видать, что-то сравнительно древнее.
M> Серьёзное метапрограммирование — это реализация компилируемых eDSLей.
DSL DSLю рознь.
M> http://lambda-the-ultimate.org/node/3281
Интересненько
Здравствуйте, Mr.Cat, Вы писали:
MC>Их можно матчить в syntax-rules. Просто указываешь в опредлении макры, что tag — не синтаксическая переменная, а должен встретиться такой символ.
На syntax-rules ты вообще не сделаешь нормальный pattern matching, в принципе.
И как это я укажу "при определении макры"? А если я хочу матчить, например ((for $$M:id in $expr1 do $expr2) ...)?
Где мне указывать, что for, in и do — символы? Как мне проще и короче указать, что id — непременно символ, а не число или список?
Зачем мне прогибаться под уродство гигиены, если без неё лучше? Всегда лучше, без исключений. Инструмент не должен навязывать мне свои нелепые ограничения.
M>>Везде гигиена только навредила бы. MC>Вредит часто не гигиена, а неумение (нежелание) ее использовать.
Ну а с чего бы желать использовать что-то настолько кривое и неудобное? Мне код писать надо, а не изобретать кривые хитрые способы обмана гигиены.
MC> Паттерн-мачинг прекрасно реализуется с гигиеной.
Нет, не реализуется.
MC> Инфиксный синтаксис навскидку тоже.
Не реализуется, только исключительно уродские варианты.
MC> Def:ast не смотрел.
А макросистема должна быть универсальной. Чтоб любые DSLи можно было делать. Гигиена неуниверсальна, и при этом никакой пользы от гигиены нет и быть не может.
M>> http://lambda-the-ultimate.org/node/3281 MC>Интересненько
Посмотри, там в документации полностью исходники приведены. С гигиеной так сделать нельзя, вообще.
Здравствуйте, MasterZiv, Вы писали: MZ>CL -- промышленно применимый язык. Он готов для разработки. MZ>Со схемой в этом отношении -- я не могу дать гарантий.
Сосбсно, эта ветка отчасти следствие того, что схему хотят сделать пригодным для серьезной разработки языком. Пока практика ее использования "неровная": кто-то юзает plt в вебе, автор ypsilon пишет на ней какой-то шароварный софт (могу ошибаться), ну и т.д.
Здравствуйте, metaprogrammer, Вы писали: M> И как это я укажу "при определении макры"? А если я хочу матчить, например ((for $$M:id in $expr1 do $expr2) ...)? M>Где мне указывать, что for, in и do — символы?
(define-syntax for
(syntax-rules (in do) ...
M>Как мне проще и короче указать, что id — непременно символ, а не число или список?
Проще и короче — нигде, т.к. ты все равно к нему будешь биндить.
M>>Где мне указывать, что for, in и do — символы?
MC>(define-syntax for MC> (syntax-rules (in do) ...
Во первых, это криво. Представь, что у тебя под сотню паттёрнов...
Во вторых, syntax-rules средствами syntax-rules не реализуется. А сам он для произвольных списков, векторов и прочего не приспособлен, он для syntax objects только.
M>>Как мне проще и короче указать, что id — непременно символ, а не число или список? MC>Проще и короче — нигде, т.к. ты все равно к нему будешь биндить.
Обращаюсь я к имени id. Ты не понял — в шаблоне сказано, что на этом месте распознаётся только символ. Аналогично можно, например, только строку, только число, или только что-то удовлетворяющее заданному предикату, и т.п. По сравнению с этим pattern matching-ом всякие там syntax-case — это убожество. Кстати, моя реализация syntax-rules и syntax-case — 150 строк с комментариями. Без гигиены, но исключительно по причине презрения к таковой. Сложного в ней ничего нет.
Здравствуйте, metaprogrammer, Вы писали: M> Обращаюсь я к имени id. Ты не понял — в шаблоне сказано, что на этом месте распознаётся только символ. Аналогично можно, например, только строку, только число, или только что-то удовлетворяющее заданному предикату, и т.п. По сравнению с этим pattern matching-ом всякие там syntax-case — это убожество.
Проверить, что за литерал приехал в syntax-rules — нельзя. Можно в syntax-case сделать syntax->datum, только зачем? Чтобы что-то вычислять в expand-time?
M>Кстати, моя реализация syntax-rules и syntax-case — 150 строк с комментариями.
Код в студию.
Здравствуйте, Mr.Cat, Вы писали:
MC>Проверить, что за литерал приехал в syntax-rules — нельзя. Можно в syntax-case сделать syntax->datum, только зачем? Чтобы что-то вычислять в expand-time?
Ваще-то pattern matching нужен далеко не только для написания макр. У него миллионы других применений имеется.
M>>Кстати, моя реализация syntax-rules и syntax-case — 150 строк с комментариями. MC>Код в студию.
Здравствуйте, metaprogrammer, Вы писали: MC>>Проверить, что за литерал приехал в syntax-rules — нельзя. Можно в syntax-case сделать syntax->datum, только зачем? Чтобы что-то вычислять в expand-time? M> Ваще-то pattern matching нужен далеко не только для написания макр. У него миллионы других применений имеется.
А вне макр матчить литерал заданного типа и подавно бессмысленно. Т.е. 6 пропускаем, а (+ 1 2 3) — нет? Не улавливаю ход твоих мыслей.
Здравствуйте, Mr.Cat, Вы писали:
M>> Ваще-то pattern matching нужен далеко не только для написания макр. У него миллионы других применений имеется. MC>А вне макр матчить литерал заданного типа и подавно бессмысленно.
Да ну? Очень даже осмысленно. Это ведь не ML и не Haskell, строгих ADT нет — так что сложные структуры только в списках и представимы. И эти структуры деструктурировать надо по всякому, по разному. Так что и предикаты нужны, и самые разные варианты ellipsis, и хитрые биндинги (например, задать имя для всей подструктуры, и при этом определить структуру её элементов). Чем мощнее pattern matching, тем проще с разными структурами работать.
MC> Т.е. 6 пропускаем, а (+ 1 2 3) — нет? Не улавливаю ход твоих мыслей.
Ты думаешь только о коде. Подумай ширше, о списках и векторах вообще.
И, кстати, даже если и код — для 6 у нас может один паттёрн срабатывать, а для (+ 1 2 3) уже совсем другой.