#(foo %)
- просто сокращение от (fn [arg] (foo arg))
.Нет причин писать макрос, который расширяется до #(...)
.Все %
в конструкции #(...)
в любом случае сразу развертываются в gensyms.
user> `#(foo % %1 %2)
(fn* [user/p1__1877 user/p2__1878]
(user/foo user/p1__1877 user/p1__1877 user/p2__1878))
Если вы когда-либо пишете макрос, который расширяется для создания анонимных функций, вы можете просторазверните их до fn
форм самостоятельно.В вашем случае вам, вероятно, следует просто использовать fn
напрямую и пропустить макросы.fn
- это Clojure lambda
.
Разница между (fn [] ...)
и (lambda () ...)
в этом случае заключается в том, что «fn» короче типа, чем «лямбда», а fn
принимает вектор дляего привязки, тогда как lambda
занимает список.Если вы используете Clojure, вам в конечном итоге придется к этому привыкнуть, поскольку векторы всегда используются для наборов привязок во всех формах do
, а также в for
и binding
и т. Д.Я понимаю, что списки используются для вызовов функций или макросов, а векторы используются для вещей, которые не являются вызовами (списки символов для привязки, например).Возможно, это облегчает визуальное сканирование кода, а не списки.Clojure - это не Common Lisp, и вы будете испытывать боль, если попытаетесь заставить его быть.
Если вы действительно, действительно хотели это сделать, просто сказать, что вы это сделали:
user> (defmacro lambda [args & body]
`(fn ~(vec args) ~@body))
user> ((lambda (x) (println x)) "foo")
foo
nil
Это не позволяет вам, помимо всего прочего, помещать строку документации или метаданные в вашу функцию.Я не думаю, что вы захотите использовать это в настоящей программе Clojure.