Правильно, что гомойконичность делает написание макросов Clojure очень простым. По сути, они позволяют вам писать код, который строит любой код, который вы хотите, используя философию «код - данные» Lisp.
Макросы на гомоиконическом языке также чрезвычайно мощные. Я нашел забавную презентацию, в которой они реализуют синтаксис запросов, подобный LINQ, всего в трех строках Clojure .
Как правило, макросы Clojure потенциально полезны по многим причинам:
Структуры управления - возможно создание определенных структур управления с использованием макросов, которые никогда не могут быть представлены как функции . Например, вы не можете написать if
как функцию, потому что, если бы она была функцией, ей пришлось бы оценивать все три аргумента, тогда как с помощью макроса вы можете сделать так, чтобы он оценивал только два (значение условия и либо истинное значение). или ложное выражение)
Оптимизация времени компиляции - иногда вы хотите оптимизировать свой код на основе известной или вычисляемой константы во время компиляции. Например, вы можете создать функцию «протоколирования», которая регистрирует журнал, только если код был скомпилирован в режиме отладки, но создает нулевые накладные расходы в производственном приложении.
Генерация кода / устранение шаблонов - если вам нужно создать много очень похожих кодов с похожей структурой, то вы можете использовать макросы для автоматической генерации их из нескольких параметров. Если вы ненавидите шаблон, то ваши макросы - ваши друзья.
Создание нового синтаксиса - если вы видите необходимость определенного фрагмента синтаксиса, который был бы полезен (возможно, инкапсулирует общий шаблон), тогда вы можете создать макрос для реализации этого. Например, некоторые DSL можно упростить с помощью дополнительного синтаксиса.
Создание нового языка с совершенно новой семантикой (Кредиты для SK-Logic!) Теоретически вы могли бы даже пойти так далеко, чтобы создать новый язык с использованием макросов, который бы эффективно компилировал ваш новый язык вниз в Clojure. Новый язык даже не должен был бы быть похожим на Lisp: он мог бы, например, анализировать и компилировать произвольные строки.
Один важный совет: используйте макросы, только если они вам нужны и функции не будут работать . Большинство проблем можно решить с помощью функций. Помимо того, что макросы излишни для простых случаев, функции обладают некоторыми внутренними преимуществами: они более гибкие, могут храниться в структурах данных, могут передаваться в качестве параметров функциям более высокого порядка, людям немного легче понять и т. Д.