Не-C ++ языки для генеративного программирования? - PullRequest
24 голосов
/ 22 сентября 2008

C ++, пожалуй, самый популярный язык для статического метапрограммирования и Java не поддерживает его .

Существуют ли другие языки, кроме C ++, которые поддерживают генеративное программирование (программы, создающие программы)?

Ответы [ 14 ]

32 голосов
/ 22 сентября 2008

Альтернативой метапрограммированию в стиле шаблона является Macro-стиль, который вы видите в различных реализациях Lisp. Я бы посоветовал загрузить Пола Грэма * на Лиспе , а также взглянуть на Clojure , если вы заинтересованы в Лиспе с макросами, работающими на JVM.

Макросы в Лиспе намного мощнее стиля C / C ++ и сами по себе представляют собой язык - они предназначены для метапрограммирования.

24 голосов
/ 23 сентября 2008

позвольте мне перечислить несколько важных деталей о том, как метапрограммирование работает в lisp (или схема , или шифер или выберите свой любимый «динамический» язык):

  • при выполнении метапрограммирования в lisp вам не нужно иметь дело с двумя языками . код мета-уровня написан на том же языке, что и код уровня объекта, который он генерирует. Метапрограммирование не ограничивается двумя уровнями, а также облегчает работу мозга.
  • в lisp у вас есть компилятор , доступный во время выполнения . на самом деле, различие между временем компиляции и временем выполнения выглядит очень искусственным и очень сильно зависит от того, куда вы помещаете свою точку зрения. в lisp простым вызовом функции вы можете скомпилировать функции в машинные инструкции, которые вы можете использовать с тех пор как объекты первого класса; то есть они могут быть неназванными функциями, которые вы можете хранить в локальной переменной, или глобальной хеш-таблицей и т. д. *
  • макросы в lisp очень просты: набор функций, помещенных в хеш-таблицу и переданных компилятору. для каждой формы, которую собирается компилятор, он обращается к этой хеш-таблице. если она находит функцию, то вызывает ее во время компиляции с исходной формой, а вместо исходной формы она компилирует форму, которую возвращает эта функция. (по модулю некоторые не важные детали), поэтому макросы lisp в основном являются плагинами для компилятора .
  • Написание функции lisp в lisp, которая оценивает код lisp, занимает около двух страниц кода (обычно это называется eval ). в такой функции у вас есть все возможности для введения любых новых правил на мета-уровне. (чтобы запустить его быстро, потребуется некоторое усилие, хотя ... примерно так же, как при запуске нового языка ...:)

случайные примеры того, что вы можете реализовать как пользовательскую библиотеку , используя метапрограммирование lisp (это реальные примеры распространенных библиотек lisp):

  • расширить язык с помощью продолжений с разделителями (hu.dwim.delico)
  • реализует макрос js-to-lisp-rpc , который можно использовать в javascript (который генерируется из lisp). он расширяется в смесь кода js / lisp, который автоматически публикует (в запросе http) все указанные локальные переменные, декодирует их на стороне сервера, запускает тело кода lisp на сервере и возвращает возвращаемое значение в javascript сторона.
  • добавить пролог, похожий на возврат к языку, который очень легко интегрируется с "нормальным" кодом lisp (см. Screamer)
  • и Расширение XML-шаблонов для общего lisp (включает пример макросов читателя , которые являются плагинами для парсера lisp)
  • тонна небольших DSL, таких как loop или итерация для легкого зацикливания
13 голосов
/ 22 сентября 2008

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

Шутки с этим примерно в 98 году заставили меня искать лучшие решения. Я мог бы написать полезные системы, которые полагались на это, но они были адскими. Из-за того, что я начал копаться, я попал в Common Lisp. Конечно, механизм шаблонов завершен по Тьюрингу, но, опять же, он является интеркальным.

Common Lisp выполняет метапрограммирование `правильно '. Пока вы делаете это, у вас есть все возможности языка, нет специального синтаксиса, и поскольку язык очень динамичен, вы можете делать с ним больше.

Есть и другие варианты, конечно. Никакой другой язык, который я использовал, не делает метапрограммирование лучше, чем Lisp, поэтому я использую его для исследовательского кода. Хотя есть много причин, по которым вы можете попробовать что-то другое, но это все будет компромиссом. Вы можете взглянуть на Haskell / ML / OCaml и т. Д. Во многих функциональных языках есть что-то похожее на мощь макросов Lisp. Вы можете найти некоторые вещи, нацеленные на .NET, но все они довольно незначительны (с точки зрения базы пользователей и т. Д.). Ни один из крупных игроков в промышленно используемых языках не имеет ничего подобного, на самом деле.

11 голосов
/ 22 сентября 2008

Nemerle и Boo - мои личные фавориты для таких вещей. Nemerle имеет очень элегантный макрос-синтаксис, несмотря на плохую документацию. Документация Boo превосходна, но ее макросы немного менее элегантны. Оба работают невероятно хорошо, однако.

Оба предназначены для .NET, поэтому они могут легко взаимодействовать с C # и другими языками .NET - даже двоичными файлами Java, если вы используете IKVM.

Редактировать: Чтобы уточнить, я имею в виду макросы в смысле слова Лисп, а не макросы препроцессора Си. Это позволяет определять новый синтаксис и тяжелое метапрограммирование во время компиляции. Например, Nemerle поставляется с макросами, которые будут проверять ваши SQL-запросы к вашему SQL-серверу во время компиляции.

9 голосов
/ 28 июля 2015

Nim - это относительно новый язык программирования, который имеет обширную поддержку статического метапрограммирования и производит эффективный (подобный C ++) код.

http://nim -lang.org /

Он поддерживает оценку функции во время компиляции, преобразования AST-кода в виде шрифта с помощью макросов, отражение во время компиляции, универсальные типы, которые можно параметризовать с произвольными значениями, и переписывание терминов, которые можно использовать для создания пользовательского высокоуровневого типичная оптимизация глазка. В процессе компиляции можно даже запускать внешние программы, которые могут влиять на генерацию кода. В качестве примера рассмотрите возможность обращения к локально работающему серверу базы данных, чтобы убедиться, что определение ORM в вашем коде (предоставляемое через некоторые DSL) соответствует схеме базы данных.

6 голосов
/ 22 сентября 2008

"D" язык программирования подобен C ++, но имеет гораздо лучшую поддержку метапрограммирования. Вот пример трассировки лучей, написанный с использованием только метапрограммирования во время компиляции:

Ctrace

Кроме того, есть ветка gcc, называемая «Concept GCC», которая поддерживает схемы метапрограммирования, которых нет в C ++ (по крайней мере, пока).

Концепция GCC

5 голосов
/ 23 сентября 2008

Common Lisp поддерживает программы, которые пишут программы несколькими различными способами.

1) Данные программы и "абстрактное синтаксическое дерево" программы единообразны (S-выражения!)

2) defmacro

3) Считыватель макросов.

4) MOP

Из них настоящим воздуходувом является СС. Читайте «Искусство протокола метаобъекта». Я обещаю, что все изменится!

4 голосов
/ 22 сентября 2008

Я рекомендую Haskell . Вот документ , описывающий его возможности метапрограммирования во время компиляции.

3 голосов
/ 19 ноября 2008

Много работы на Haskell: доменные языки (DSL), исполняемые спецификации, преобразование программ, частичное применение, поэтапные вычисления. Несколько ссылок для начала работы:

2 голосов
/ 14 июня 2009

Большинство людей пытаются найти язык, который имеет «предельное отражение» для самопроверки и что-то вроде «eval» для придания нового кода. Такие языки трудно найти (LISP - главный контрпример) и они, конечно, не мейнстрим.

Но другой подход заключается в использовании набора инструментов, которые могут проверять, генерировать и манипулировать программным кодом. Джекпот такой инструмент сосредоточены на Java. http://jackpot.netbeans.org/

Наш инструментарий реинжиниринга программного обеспечения DMS такой инструмент, который работает на C, C ++, C #, Java, COBOL, PHP, Javascript, Ada, Verilog, VHDL и множество других языков. (Он использует производственные интерфейсы качества, чтобы позволить ему читать все эти языки). Более того, он может сделать это с несколькими языками одновременно. Смотри http://www.semdesigns.com/Products/DMS/DMSToolkit.html

DMS преуспевает, потому что обеспечивает регулярный метод и инфраструктуру поддержки для полного доступа к структуре программы в виде AST, и в большинстве случаев дополнительные данные, такие как таблицы символов, информация о типах, контроль и анализ потока данных, все необходимые для выполнения сложной программы манипуляция.

...