Сравнение общих макросов Lisp и возможностей метапрограммирования Forth
Каждый программист Common Lisp знает, что макросы являются мощным инструментом. Общие макросы Lisp были использованы, среди прочего, для добавления ориентации объектов поверх Lisp без изменения спецификации языка; read-macros - это еще одна конструкция с возможностями изгиба ума.
Другая программа, которая позволяет метапрограммировать Forth. Форт делает это несколько иначе, используя "слова" и "генерировать слова".
Я хотел бы знать, от кого-то, кто ругался на обоих языках, если общие макросы и конструкторы Lisp сопоставимы по ширине/мощности: есть ли что-то, что вы можете сделать с тем, что вы не можете сделать с помощью последний? Или наоборот?
Конечно, я не говорю о Turing-полноте двух языков: я говорю о возможностях metaprogramming. C является завершением Тьюринга, но только глупец утверждает, что макросы C сравнимы по мощности с Common Lisp.
Ответы
Ответ 1
На мой взгляд, общие макросы Lisp похожи на быстрые слова Forth. (На самом деле они наиболее похожи на макросы чтения Lisp.)
-
Они оба являются процедурными макросами, то есть могут использовать полную мощность языка.
-
Оба они имеют доступ к исходному коду.
-
Оба они могут выводить все, что выражается на языке. (Например, объектно-ориентированное расширение в Lisp или базовые конструкции потока управления в Forth.)
Основное отличие, возможно, в том, что входные макросы Forth являются символьными строками, а макросы Lisp работают на дереве разбора.
Ответ 2
Я - разработчик Forth и имею большой опыт в Forth, полдюжины реализаций, несколько сотен проблем проектировщика. Я также сделал небольшое объектно-ориентированное расширение (маленькое, то есть дюжина строк или около того). Мой опыт в LISP намного больше на уровне курса, но я думаю, что будет справедливо сказать, что средства метапрограммирования LISP более систематичны и на практике более мощны.
Относительно легко построить абстракции поверх абстракций в LISP. В Forth, если я хочу определить матрицу на линейном пространстве, определенном объектами с нетривиальными определениями.. Я переключаюсь на Python.
Причина также очевидна, по крайней мере, для меня. Создатели LISP, где математики, в то время как Чак Мур - лучший пример практического программиста, никогда не тратят свое время на теоретическую проблему.
Это распространяется на этот вопрос следующим образом. Макрос lisp имеет структуру в контексте Lisp и, по крайней мере, предлагает значение, соответствующее общим принципам lisp. Непосредственное слово Forth - это просто другая программа, которая может означать и делать что угодно, включая приготовление из нее обеда для собак.
Ответ 3
Извините, если обсуждение ниже может показаться немного расплывчатым, но есть слишком много, чтобы сказать.
У меня есть только теоретические знания Lisp, а не руки.
С другой стороны, Forth мог иметь (но нормальный Forth не) полное метапрограммирование внутри языка. Но метапрограммирование рассматривается и возможно, но без согласованного синтаксиса. Я думаю, что то же самое происходит в Lisp.
Я реализовал очень чистое решение, включающее эту возможность в небольшой парадигме Форта, как язык. Чтобы иметь метапрограммирование, мы должны иметь возможность ссылаться на то, что мы пишем. Поэтому, когда мы пишем программу для немедленного выполнения:
bread eat
мы также должны иметь возможность ссылаться на ту же фразу с намерением, а не на ее выполнение, чтобы сохранить ее для последующей ссылки. Это можно сделать, например,
{ bread eat }
Вышеупомянутая фраза может иметь как следствие оставить созданный объект в стеке. Но поскольку мы создали новое слово как {
и }
, мы также имеем право ссылаться на это.
Итак, мы могли бы сослаться на:
{ bread
Как мы можем на это ссылаться? Ориентировочный синтаксис: {{ { bread }}
.
Если мы приведем название XXX
к предыдущей фразе, мы могли бы написать начальную фразу как:
XXX eat }
и фраза выше должна корректно работать, оставляя в стеке
{ bread eat }
Как я не знаю, что именно я говорю, именно то, что вы ищете, достаточно сказать, что по приведенным выше рассуждениям и их реализации внутри Forth каждое слово получает уровень выполнения и определяет, который является уровнем метапрограммирования слова.
Очевидно, что мы имеем первый уровень бесконечности и каждый последующий уровень. Таким образом, уровни выполнения основаны на математической бесконечности.
Я реализовал вышеупомянутое внутри своего рода Forth и на первом уровне (ниже бесконечности) все работает плавно. Так, например, я могу изменить синтаксис:
{ bread eat } { tomatos eat } x 3 = if
в
{ bread eat | tomatos eat } x 3 = if
Это делается путем определения |
как } {
как ниже:
{{ } { }} "|" define
или если вам это нравится лучше:
2{ } { 2} "|" define
Вышеприведенный метод берет внутри языка с правильным синтаксисом метаязык и делает его языком.
Таким образом, по моему мнению, оба Lisp и Forth имеют возможность метапрограммирования, но обе не имеют такой возможности как интегрирующей части языка.
У меня есть более подробная информация об этом на napl.wikispaces.com.