Языки, отличные от C++ для генеративного программирования?

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

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

Я и раньше жаловался на модерацию StackOverflow, но позвольте мне воздержаться здесь и просто указать на наблюдение ... видите ли вы здесь перегрузку «дебатов, аргументов, опросов или расширенных обсуждений»? Если это то, чего мы боимся, давайте оценим, насколько это плохо в ответах на этот вопрос. Если вместо ужасного эпизода с Джерри Спрингером мы вместо этого увидим разумную, ценную информацию, которой с уважением делятся и которую ценят, тогда, возможно, нам следует оставить этот вопрос открытым. В противном случае мы слишком беспокоимся о проблемах, которых у нас даже нет.

Charlie Flowers 14.09.2012 20:38

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

jwfearn 15.09.2012 18:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
24
2
3 774
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Lisp поддерживает форму «метапрограммирования», хотя и не в том же смысле, что и метапрограммирование шаблонов C++. Кроме того, ваш термин «статический» может означать разные вещи в этом контексте, но Lisp также поддерживает статическую типизацию, если вы это имеете в виду.

Я понимаю «статическое метапрограммирование» как означающее преобразование кода во время компиляции в противоположность динамическому перехвату / изменению поведения во время выполнения (как, например, с метаклассами или EVAL). В этом смысле макросы Lisp - это своего рода средство статического метапрограммирования. ОП, это ты имеешь в виду?

Matthias Benkard 23.09.2008 14:28

Lisp не зря называют «программируемым языком программирования». Он позволяет / поощряет гораздо более общую форму «метапрограммирования», чем такие вещи, как подход с использованием шаблонов С ++.

simon 25.09.2008 01:58

@ Маттиас, да, я именно это имел в виду. Спасибо!

jwfearn 22.01.2009 18:35
Ответ принят как подходящий

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

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

Хм, а как макросы Lisp - это самостоятельный язык? Это весь Лисп, в этом его прелесть.

Luís Oliveira 23.09.2008 02:50

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

Lou Franco 23.09.2008 03:11

Вы также не можете добавлять в свой Lisp функции (или переменные, или специальные операторы, или ...) с помощью набора макросов. Значит, функции - это тоже язык сами по себе?

Matthias Benkard 23.09.2008 14:20

добавление макросов к lisp, у которых раньше не было макросов, на самом деле довольно просто и не требует изменения конструкций мета-уровня, таких как специальные операторы. дьявол, конечно, кроется в деталях, но v0.1 - это вопрос пары страниц ...

Attila Lendvai 24.09.2008 22:33

Прав ли я, думая, что метапрограммирование Lisp не статично (то есть во время компиляции)?

Paul Biggar 19.08.2009 14:34

Макросы Lisp могут быть включены в различные фазы компилятора. Я не эксперт, но есть макросы чтения, которые вызываются во время синтаксического анализа, и макросы времени компиляции, которые, например, генерируют код. Думаю, есть и другие.

Lou Franco 20.08.2009 04:33

Существуют «макросы чтения», они используются при чтении исходного кода (из REPL или из файла) и преобразовании исходного кода во внутреннее представление. Есть «нормальные» макросы, они используются во время «времени расширения макроса» (это делается, по сути, на «минимальной фазе компиляции», что довольно близко к определению функции). Существуют «макросы компилятора», которые работают как функции замены компиляции всей функции, где вы можете испускать различный код в зависимости от того, что у вас есть, например, константы, переменные, ограничения известных типов и тому подобное.

Vatine 01.10.2010 16:28

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

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

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

Спасибо за ответы, возможно, вы могли бы отредактировать, чтобы добавить ссылки для Nemerle и Boo?

jwfearn 22.09.2008 23:17

Сайт для nemerle - nemerle.org. Бу находится по адресу boo.codehaus.org

catbert 16.04.2010 20:41

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

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

Ctrace

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

Концепция 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.

jwfearn 23.09.2008 02:08

Злоупотреблять или не злоупотреблять, но на самом деле у вас нет другого выбора для написания универсального кода на C++.

NN_ 08.03.2011 12:12

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

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

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

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

Спасибо за отличный ответ. Согласно другому ответу, я проверял Clojure (вариант Lisp, работающий на JVM). Возможно, вам это будет интересно. Предложение: добавьте больше ссылок (например, slate, cl-delico, screamer и т. д.) Поиск - это нормально, но ссылка экономит время читателей.

jwfearn 23.09.2008 19:13

мне Clojure не интересен. он просто более доступен для 80% аудитории и, следовательно, становится все более популярным ... хотя язык программирования ядра, проект FONC на VPRI.org действительно интересны.

Attila Lendvai 10.04.2012 10:50

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

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

2) defmacro

3) Читательские макросы.

4) СС

Из них самый настоящий умопомрачитель - это СС. Прочтите «Искусство протокола метаобъектов». Обещаю, это все изменит для вас!

Спасибо за ответ, обязательно проверю СС! Предложение: чтобы сэкономить время читателей, отредактируйте ответ, чтобы добавить ссылки или информацию о публикации для ваших ссылок.

jwfearn 23.09.2008 22:50

Горные породы СС; Kizcales теперь занимается аспектно-ориентированным программированием, которое можно рассматривать как MOP для Java, C# и т. д.

ja. 19.11.2008 09:50

Семейство языков 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++) скомпилированный код.

http://nim-lang.org/

Он поддерживает оценку функций во время компиляции, 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>

Но вы не ограничены уровнем абстракции построенного графа объектов: вы можете не только свободно добавлять свои собственные типы, но и граф объектов может интерпретировать сам себя и, таким образом, может изменять себя так же, как списки в Лиспе.

Другие вопросы по теме