Во многих языках есть специальный механизм генерации кода — макросы.
Иногда они реализованы на отдельном, довольно примитивном языке, основанном на простой подстановке текста (препроцессоры PL/I и C, m4), но даже в такой версии можно делать интересные и полезные вещи.
Другой популярный вариант — реализация макросов на том же языке, что и программа, в которой они используются.
Этот подход берет начало от Lisp (удобен тем, что формат программ и данных один и тот же), активно используется в Julia, OCaml (camlp4/5), Scala, Haskell, Rust и наиболее развит в Nemerle, где макрос может запускаться как до, так и после проверки типов и вывода, и в последнем варианте иметь доступ к типам.
При этом все возможности языка в макросах не нужны; например, высокая эффективность и безопасность Rust здесь не принесет никакой пользы и может только усложнить разработку.
Кроме того, все это функциональные или императивные языки, и меня заинтересовало, что может дать логический язык с точки зрения написания макросов.
Возникла идея реализовать Пролог в Nemerle, но вдруг выяснилось, что последний, несмотря на заботу одной крупной и известной компании, умер, а компилятор глючит на доступных версиях mono. Тогда я решил (надеюсь временно) снизить планку и попробовать просто функциональную, но относительно простую во встраивании глюон .
Макросы в Rust приходится упаковывать в отдельный пакет, что не очень удобно, если вы хотите разработать макрос для одноразового использования.
Так почему бы не реализовать макрос, который просто получает код Gluon в качестве параметра и выполняет его ? Теперь Gluon должен вернуть строку, которая будет анализироваться как код Rust. Мне, конечно, хотелось бы иметь возможность возвращать массив токенов, но мне не удалось получить необходимые типы в Gluon. Думаю, такой подход может быть востребован для «одноразовых» макросов.
Предположим, мы хотим инициализировать статический массив нулями, за исключением нескольких указанных.
Вы можете просто написать
В немного более сложном пример создается массив простых чисел — здесь удобно использовать макрос, но создавать для него отдельный пакет задача не стоит, и можно написать генерирующий код на месте.static MASK: [i32; 64] = glumacro::a_proc_macro!(r#" let array = import! std.array let s = [13, 17, 42] let inl x = array.foldable.foldr (\y a -> a || x == y) False s rec let f n = if n == 64 then [] else array.append [if inl n then 1 else 0] (f (n+1)) in show (f 0) "#);
Теги: #Аномальное программирование #Функциональное программирование #Rust #nemerle #gluon #macro
-
Чем Может Помочь Чит Для Starcraft 2?
19 Oct, 24 -
Процесс Поисковой Оптимизации
19 Oct, 24 -
Отходы Идут В Духовку
19 Oct, 24 -
Немного О Работе С Контейнерами
19 Oct, 24 -
Блокчейн Глазами Разработчика
19 Oct, 24