C++, вероятно, самый популярный язык для статическое метапрограммирование и Java не поддерживает это.
Существуют ли какие-либо другие языки, помимо C++, которые поддерживают генеративное программирование (программы, создающие программы)?
Я отредактировал этот вопрос, чтобы удалить запросы на «лучшее». Пожалуйста, подумайте о повторном открытии. Кстати: именно благодаря ответам на этот вопрос я впервые услышал о Clojure. Так что для меня это было конструктивно. Спасибо тем, кто ответил и прокомментировал!





Lisp поддерживает форму «метапрограммирования», хотя и не в том же смысле, что и метапрограммирование шаблонов C++. Кроме того, ваш термин «статический» может означать разные вещи в этом контексте, но Lisp также поддерживает статическую типизацию, если вы это имеете в виду.
Я понимаю «статическое метапрограммирование» как означающее преобразование кода во время компиляции в противоположность динамическому перехвату / изменению поведения во время выполнения (как, например, с метаклассами или EVAL). В этом смысле макросы Lisp - это своего рода средство статического метапрограммирования. ОП, это ты имеешь в виду?
Lisp не зря называют «программируемым языком программирования». Он позволяет / поощряет гораздо более общую форму «метапрограммирования», чем такие вещи, как подход с использованием шаблонов С ++.
@ Маттиас, да, я именно это имел в виду. Спасибо!
Альтернативой метапрограммированию в стиле шаблона является Макро-стиль, который вы видите в различных реализациях Лиспа. Я бы посоветовал загрузить На Лиспе Пола Грэма, а также взглянуть на Clojure, если вас интересует Lisp с макросами, который работает на JVM.
Макросы в Лиспе намного мощнее, чем стиль C / C++, и сами по себе составляют язык - они предназначены для метапрограммирования.
Хм, а как макросы Lisp - это самостоятельный язык? Это весь Лисп, в этом его прелесть.
Макросы немного отличаются от Lisp, поскольку они не вычисляются, и кучу специальных операторов. Я не думаю, что вы можете создавать макросы с помощью Lisp (в том смысле, что вы не можете добавлять макросы в ваш Lisp с помощью всего лишь набора функций).
Вы также не можете добавлять в свой Lisp функции (или переменные, или специальные операторы, или ...) с помощью набора макросов. Значит, функции - это тоже язык сами по себе?
добавление макросов к lisp, у которых раньше не было макросов, на самом деле довольно просто и не требует изменения конструкций мета-уровня, таких как специальные операторы. дьявол, конечно, кроется в деталях, но v0.1 - это вопрос пары страниц ...
Прав ли я, думая, что метапрограммирование Lisp не статично (то есть во время компиляции)?
Макросы Lisp могут быть включены в различные фазы компилятора. Я не эксперт, но есть макросы чтения, которые вызываются во время синтаксического анализа, и макросы времени компиляции, которые, например, генерируют код. Думаю, есть и другие.
Существуют «макросы чтения», они используются при чтении исходного кода (из REPL или из файла) и преобразовании исходного кода во внутреннее представление. Есть «нормальные» макросы, они используются во время «времени расширения макроса» (это делается, по сути, на «минимальной фазе компиляции», что довольно близко к определению функции). Существуют «макросы компилятора», которые работают как функции замены компиляции всей функции, где вы можете испускать различный код в зависимости от того, что у вас есть, например, константы, переменные, ограничения известных типов и тому подобное.
Nemerle и Бу - мои личные фавориты для таких вещей. Nemerle имеет очень элегантный синтаксис макросов, несмотря на плохую документацию. Документация Boo превосходна, но ее макросы менее элегантны. Однако оба работают невероятно хорошо.
Оба нацелены на .NET, поэтому они могут легко взаимодействовать с C# и другими языками .NET - даже с двоичными файлами Java, если вы используете IKVM.
Обновлено: Чтобы уточнить, я имею в виду макросы в смысле слова Lisp, а не макросы препроцессора C. Это позволяет определять новый синтаксис и тяжелое метапрограммирование во время компиляции. Например, Nemerle поставляется с макросами, которые будут проверять ваши SQL-запросы на вашем SQL-сервере во время компиляции.
Спасибо за ответы, возможно, вы могли бы отредактировать, чтобы добавить ссылки для Nemerle и Boo?
Сайт для nemerle - nemerle.org. Бу находится по адресу boo.codehaus.org
Язык программирования "D" похож на C++, но имеет гораздо лучшую поддержку метапрограммирования. Вот пример трассировщика лучей, написанного с использованием только метапрограммирования во время компиляции:
Кроме того, существует ветвь gcc под названием «Concept GCC», которая поддерживает конструкции метапрограммирования, которых нет в C++ (по крайней мере, пока).
«метапрограммирование» - действительно плохое имя для этой конкретной функции, по крайней мере, когда вы обсуждаете более одного языка, поскольку эта функция нужна только для узкого сегмента языков, а именно:
исключить любой из них, и «статическое метапрограммирование» просто не имеет смысла. поэтому я был бы удивлен, если бы в каком-нибудь отдаленно распространенном языке было что-то подобное, как это понимается на C++.
конечно, динамические языки и несколько функциональных языков поддерживают совершенно разные концепции, которые также можно назвать метапрограммированием.
Конечно же, метаязык (ML): http://cs.anu.edu.au/student/comp8033/ml.html
Метапрограммирование шаблонов - это, по сути, злоупотребление механизмом шаблонов. Я имею в виду, что вы получаете в основном то, что ожидаете от функции, которая была незапланированным побочным эффектом - это беспорядок и (хотя инструменты становятся лучше) настоящая заноза в заднице, потому что язык не поддержать вас в этом (я должен отметить, что мой опыт работы с последними достижениями в этом вопросе устарел, поскольку я по сути отказался от этого подхода. Однако я не слышал о каких-либо больших успехах)
Попытки возиться с этим примерно в 98-м году заставили меня искать лучшие решения. Я мог бы написать полезные системы, основанные на нем, но они были адскими. В конце концов, поиски привели меня к Common Lisp. Конечно, механизм шаблонов завершен по Тьюрингу, но, опять же, интеркальный.
Common Lisp выполняет метапрограммирование "правильно". Пока вы это делаете, у вас есть все возможности языка, никакого специального синтаксиса, а поскольку язык очень динамичен, вы можете делать с ним больше.
Конечно, есть и другие варианты. Ни один другой язык, который я использовал, не справляется с метапрограммированием лучше, чем Lisp, поэтому я использую его для исследования кода. Хотя есть много причин, по которым вы можете захотеть попробовать что-то еще, но все это будет компромиссом. Вы можете посмотреть Haskell / ML / OCaml и т. д. Во многих функциональных языках есть что-то, приближающееся к мощности макросов Lisp. Вы можете найти кое-что, ориентированное на .NET, но все они довольно маргинальны (с точки зрения пользовательской базы и т. д.). На самом деле, ни у одного из крупных игроков в сфере промышленных языков нет ничего подобного.
Спасибо за Ваш ответ! MP с шаблонами C++ определенно беспорядок (это одна из причин моего вопроса). Когда / если C++ 0x доступен от поставщиков компиляторов, он должен стать немного чище, поскольку многие из новых языковых функций предназначены специально для поддержки MP.
Злоупотреблять или не злоупотреблять, но на самом деле у вас нет другого выбора для написания универсального кода на C++.
позвольте мне перечислить несколько важных деталей о том, как метапрограммирование работает в шепелявке (или схема, или шифер, или выберите ваш любимый «динамический» язык):
случайные примеры того, что вы можете реализовать как пользовательскую библиотеку использует метапрограммирование lisp (это реальные примеры распространенных библиотек lisp):
Спасибо за отличный ответ. Согласно другому ответу, я проверял Clojure (вариант Lisp, работающий на JVM). Возможно, вам это будет интересно. Предложение: добавьте больше ссылок (например, slate, cl-delico, screamer и т. д.) Поиск - это нормально, но ссылка экономит время читателей.
мне Clojure не интересен. он просто более доступен для 80% аудитории и, следовательно, становится все более популярным ... хотя язык программирования ядра, проект FONC на VPRI.org действительно интересны.
Common Lisp поддерживает программы, которые пишут программы несколькими способами.
1) Данные программы и "абстрактное синтаксическое дерево" программы единообразны (S-выражения!)
2) defmacro
3) Читательские макросы.
4) СС
Из них самый настоящий умопомрачитель - это СС. Прочтите «Искусство протокола метаобъектов». Обещаю, это все изменит для вас!
Спасибо за ответ, обязательно проверю СС! Предложение: чтобы сэкономить время читателей, отредактируйте ответ, чтобы добавить ссылки или информацию о публикации для ваших ссылок.
Горные породы СС; Kizcales теперь занимается аспектно-ориентированным программированием, которое можно рассматривать как MOP для Java, C# и т. д.
Семейство языков ML было разработано специально для этой цели. Одна из самых известных историй успеха OCaml - это библиотека FFTW для высокопроизводительных БПФ, которая представляет собой код C, почти полностью сгенерированный программой OCaml.
Ваше здоровье, Джон Харроп.
Много работы в Haskell: доменные языки (DSL), спецификации исполняемых файлов, преобразование программ, частичное приложение, поэтапные вычисления. Несколько ссылок для начала:
Большинство людей пытаются найти язык, который имеет "окончательное отражение" для самопроверки и что-то вроде "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, и в большинстве случаев дополнительные данные, такие как таблицы символов, информация о типах, управление и анализ потока данных, все необходимое для сложных манипуляций с программой.
Nim - относительно новый язык программирования, который имеет обширную поддержку статического метапрограммирования и создает эффективный (как C++) скомпилированный код.
Он поддерживает оценку функций во время компиляции, Lisp-подобные преобразования кода AST с помощью макросов, отражение во время компиляции, общие типы, которые можно параметризовать произвольными значениями, и переопределение терминов, которое можно использовать для создания определяемого пользователем высокоуровневого типа с поддержкой типов. глазок оптимизации. Возможно даже выполнение внешних программ в процессе компиляции, которые могут повлиять на генерацию кода. В качестве примера рассмотрите возможность разговора с локально работающим сервером базы данных, чтобы убедиться, что определение ORM в вашем коде (предоставленном через некоторый DSL) соответствует схеме базы данных.
Неважно, какой язык вы используете - любой из них может выполнять гетерогенное генеративное метапрограммирование. Возьмите любой динамический язык, например Python или Clojure, или Haskell, если вы фанат шрифтов, и писать модели на этом основном языке, которые являются способен скомпилировать себя на какой-то основной язык, которые вы хотите или вынуждены использовать вашей командой / работодателем.
Я нашел графы объектов хорошей моделью для внутреннего представления модели. Этот граф может смешивать атрибуты и упорядоченные подграфы в одном узле, который является родным для грамматики атрибутов и AST. Таким образом, интерпретация графа объектов может быть эффективным слоем между вашим основным и целевым языками и может действовать как своего рода язык без синтаксиса, определенный для структур данных.
Ближайшей моделью является AST: описывать деревья AST в Python (основной язык), цели к синтаксису C++ (целевой язык):
# from metaL import *
class Object:
def __init__(self, V):
self.val = V
self.slot = {}
self.nest = []
class Module(Object):
def cc(self):
c = '// \ %s\n' % self.head(test=True)
for i in self.nest:
c += i.cc()
c += '// / %s\n' % self.head(test=True)
return c
hello = Module('hello')
# <module:hello> #a04475a2
class Include(Object):
def cc(self):
return '#include <%s.h>\n' % self.val
stdlib = Include('stdlib')
hello // stdlib
# <module:hello> #b6efb657
# 0: <include:stdlib> #f1af3e21
class Fn(Object):
def cc(self):
return '\nvoid %s() {\n}\n\n' % self.val
main = Fn('main')
hello // main
print(hello.cc())
// \ <module:hello>
#include <stdlib.h>
void main() {
}
// / <module:hello>
Но вы не ограничены уровнем абстракции построенного графа объектов: вы можете не только свободно добавлять свои собственные типы, но и граф объектов может интерпретировать сам себя и, таким образом, может изменять себя так же, как списки в Лиспе.
Я и раньше жаловался на модерацию StackOverflow, но позвольте мне воздержаться здесь и просто указать на наблюдение ... видите ли вы здесь перегрузку «дебатов, аргументов, опросов или расширенных обсуждений»? Если это то, чего мы боимся, давайте оценим, насколько это плохо в ответах на этот вопрос. Если вместо ужасного эпизода с Джерри Спрингером мы вместо этого увидим разумную, ценную информацию, которой с уважением делятся и которую ценят, тогда, возможно, нам следует оставить этот вопрос открытым. В противном случае мы слишком беспокоимся о проблемах, которых у нас даже нет.