Прежде всего Lisp имеет функции первого класса, поэтому вы также можете спросить: «Зачем мне нужны макросы в Lisp, если у меня уже есть первоклассные функции». Ответ на этот вопрос заключается в том, что первоклассные функции не позволяют вам играть с синтаксисом.
На косметическом уровне функции первого класса позволяют писать f(filename, some_function)
или f(filename, lambda fh: fh.whatever(x))
, но не f(filename, fh, fh.whatever(x))
. Хотя, возможно, это хорошо, потому что в этом последнем случае гораздо менее ясно, откуда fh
приходит неожиданно.
Более важные функции могут содержать только действительный код. Таким образом, вы не можете написать функцию более высокого порядка reverse_function
, которая принимает функцию в качестве аргумента и выполняет ее «в обратном порядке», чтобы reverse_function(lambda: "hello world" print)
выполнил print "hello world"
. С помощью макроса вы можете это сделать. Конечно, этот конкретный пример довольно глупый, но эта способность чрезвычайно полезна при встраивании доменных языков.
Например, вы не могли реализовать общую конструкцию lisp loop
в python. Черт, вы даже не могли реализовать конструкцию python for ... in
в python, если она не была встроена - по крайней мере, не с этим синтаксисом. Конечно, вы могли бы реализовать что-то вроде for(collection, function)
, но это намного меньше.