Pull to refresh

Comments 26

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

doc.rust-lang.org/book/macros.html

зы. а вообще забавно читать про метапрограммирование и не обнаружить слова lisp.
Меня интересуют в первую очередь си-подобные языки. Ну и конечно всего не охватить в одной статье… хотя конечно Rust можно было упомянуть, я просто не успел еще разобраться с его макросами. По Rust (как и по Nim) на данный момент крайне мало документации, надеюсь в ближайшее время что-то поменяется в лучшую сторону в связи с выходом 1.0. Что же касается lisp, то это язык с сильно отличающимся от «мейнстрима» синтаксисом, этот фактор усложняет понимание.
Голый AST усложняет понимание?
Непривычный синтаксис усложняет понимание. Это примерно то же самое как в статьях, в которых пытаются объяснить что же такое монады, используются примеры на Haskell. Возможно, внутри Haskell это даже достаточно простая и естественная концепция, но когда смотришь на код, мозгу с непривычки не за что зацепиться:)
Да, похоже, система программировения — прежде всего, задачи которые в ней решаются, вне их языки не имеют очевидной семантики.
По Rust есть целая большая официальная книга, на главу которой про макросы выше привели ссылку. И Rust, кстати, всё-таки по синтаксису гораздо ближе к C, чем Nim или Nemerle.
>> сплайсинга — фичи, известной всем, кто пишет на скриптовых языках, когда в строку с помощью специального синтаксиса можно вставлять имена различных переменных

Это, вроде, интерполяцией называется.
Да, вы правы, поправил.
1. В C++ есть ещё один способ — это constexpr, который позволяет выполнение кода во время компиляции (не любого, с ограничениями).
2. Не все компиляторы C++ основаны на AST. Главный пример такого динозавра — это MS Visual Studio, из-за чего в VS сильно затруднена реализация мета-возможностей, в частности, как раз полноценной поддержки constexpr нет, и будет не скоро.
Не все компиляторы C++ основаны на AST. Главный пример такого динозавра — это MS Visual Studio

А где можно с этим ознакомиться подробнее? (интересно, на чем же он основан тогда?...)
Ну открытой информации нету. Я знаю это по комментариям Stephan T. Lavavej (псевдоним STL, мантейнер STL в микрософте), которому часто приходится на конференциях, в списках рассылки и в реддите оправдываться за плохую поддержку фич в C++.

Вероятно, они работают с потоком токенов. По слухам, оправдывают это тем, что в Микрософте много внутреннего автогенерированного кода очень большого размера (функции в десятки тысяч строк (!)) с малым использованием фич. Они утверждают, что AST компиляторы с таким объёмом кода не справятся (хотя многие компиляторные эксперты с этим утверждением не согласны). STL писал, что компиляторная команда попытается в ближайшее время достичь поддержки костылями на текущей архитектуре, а в дальнейших планах у них полное переписывание (но это займет, видимо, несколько лет).

Источники тут:
— ветка в рассылке Буста начиная отсюда: http://lists.boost.org/Archives/boost/2014/06/214317.php
— Обсуждения в реддите:
C++17 progress update!
Visual C++: quality of error messages
C++11/14/17 Features In VS 2015 RC

Ещё это обсуждалось на каких-то конференциях (вероятно CPPCon 2014), но я не помню в каких именно докладах (видео есть на Youtube, но как там что-то найти?).
Вангую, что они в конце концов задолбаются и возьмут фронтенд от clang'а.
Но с другой стороны вот https://www.reddit.com/r/cpp/comments/36uq7s/vs_2015_considers_noexcept_specs_different_if/crm9o67:
We should really do a Channel 9 video on this topic. No we haven't abandoned this. Yes, there is an AST now. There is still modernization work to be done. No, we haven't abandoned our frontend for Clang although we will also support clang. (see recent blog posts)
Странно что не рассмотрен язык MUMPS В нем еще 100 лет назад проблема решена самым удачным способом.
Средств метапрограммирования в этом языке несколько:
Команда Xecute аргументом является строка с командами MUMPS которые и выполняются
Косвенный синтаксис который позволяет имена переменных и аргументы команды задавать в виде выражения.
Команда ZInsert позволяет строку вставить в любое место программы, таким образом можно сформировать в runtime любую программу.
Команда ZSave сохраняет такую программу на диске и транслирует ее.
Все просто и элегантно. При этом никакого другого языка кроме MUMPS не надо. В других языках метапрограммирование в зачаточном состоянии. Хотя конечно препроцессор Си вещь удобная, но говорить что это метапрограммирование довольно смело.
Это называется eval. Тоже метапрограммирование, но другое, применимое в основном для интерпретируемых языков.
Почти так. Но в MUMPS таких возможностей больше. Можно команды записать в дерево, а программой просто обходить такое дерево и выполнять команды хранящиеся в вершинах.
Но я встречал упоминание о том что в Pascal можно в runtime оттранслировать команды и их выполнить.
Когда в языке есть eval(), умеющий выполнять программы в виде строк, остальное неважно — хоть в дерево эти строки подвесить, хоть в список, хоть в циклический буфер:) Но это когда язык интерпретируемый. Если язык компилируемый, то для eval() программе нужно или тащить с собой компилятор (что совсем неразумно) или — что разумнее — иметь встроенный скриптинг на скриптовом языке и интерпретатор этого языка в виде библиотеки. Хотя языковая поддержка для таких вещей все равно желательна — например для прозрачного доступа к объектам компилируемого языка из скрипта.
Безусловно надо либо транслировать текст исходного языка либо интерпретировать. Насчет неразумности я с вами не согласен. Если приложение существенно использует метапрограммирование, то это необходимо и очень разумно. Но для этого возможно нет необходимости иметь мощный оптимизирующий компилятор.
Метапрограммирование: какое оно есть и каким должно быть: LISP.
В каком из? Так-то макросы CL и Racket отличаются друг от друга.
Если честно, я не вижу фундаментальной разницы между ними. Да, они отличаются, но принцип — тот же.
При желании можно писать макросы как в CL:
gist.github.com/m1el/084477b3db4c5f6bd202
Интересно, а annotation processors в Java можно считать метапрограммированием? А манипулирование байт-кодом на уровне class loader'ов или на уровне агентов?
Спасибо, интересная статья.

Сегодня в обсуждении на reddit один товарищ рассказывал, что в Guile очень крутая система макросов. Не знаю, насколько можно доверять комментарию (комментируемая статья — довольно толстый вброс), но по слухам, guile довольно просто встраивается в софт.

Ещё в Ruby поддерживается метапрограммирование (целая книга по теме), но в детали не вникал.

Аналогично, сами шаблоны могут быть только классами (структурами) или функциями.
И переменными.
Использование того же самого языка для программ и метапрограмм не обязательно
Я с вами по большей части согласен, но и мысль иметь схожий синтаксис для языка и мета-языка тоже заманчива. В основе мета-генерации будут лежать всё равно все те же основы, что и при работе с «обычными» данными: определения, ветвления, циклы. А пройтись по мапе целых чисел или по мапе операторов языка разницы особой не имеет: суть цикл (за вычетом требования constexpr ко всем участникам последнего). Главное, чтобы вызов обычной функции и макроса в коде различались.

Я думаю, разница между языком и его мета-языком тем больше, чем более строг и статичен язык. По мере добавления динамики грань между языком и мета-языком стирается, до тех пор, пока совсем не пропадёт на уровне символических выражений Лиспа.
Sign up to leave a comment.

Articles