Ответ 1
#(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" короче, чем "lambda", а fn
берет вектор для своих привязок, тогда как lambda
принимает список. Если вы используете Clojure, вам придется привыкнуть к этому в конечном счете, потому что векторы всегда используются для коллекций привязок, во всех формах do
и в for
и binding
и т.д. Обоснование так как я понимаю, что списки используются для вызовов функций или вызовов макросов, а векторы используются для вещей, которые не являются вызовами (например, списки символов для привязки). Вероятно, это облегчает сканирование кода визуально, чем списки - все-на-пути вниз. Clojure не является общим Lisp, и вы испытаете боль, если попытаетесь заставить его быть.
Если вы действительно, действительно хотели сделать это, просто сказать, что вы сделали:
user> (defmacro lambda [args & body]
`(fn ~(vec args) [email protected]))
user> ((lambda (x) (println x)) "foo")
foo
nil
Это не позволяет вам помещать docstring или метаданные в вашу функцию, среди прочего. Я не думаю, что вы захотите использовать это в реальной программе Clojure.