Есть ли разница между синтаксисом fn и # для анонимных функций в Clojure?
Я новичок в clojure, и я видел анонимные функции, написанные как:
(fn [x] (* x x))
а также:
#(* % %)
Очевидно, что вторая более кратка. Есть ли разница? Может ли каждая анонимная функция быть представлена в любом стиле? Еще один идиоматический?
В связи с этим вопросом я не смог определить, как преобразовать (fn [x] [x x])
в последний синтаксис. Я был бы признателен за указатель на документацию, которая разъясняет эту ситуацию.
Ответы
Ответ 1
Наиболее важными отличиями являются:
-
(fn ...)
может быть вложен, #()
не может
- Вы можете лучше назвать свои параметры с помощью
(fn [x y] ..)
или аналогичного, вместо использования %
, %2
, %3
и т.д.
- Вы можете назвать функцию с
(fn ...)
для рекурсивного использования, например. (fn fib [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
- Легче создавать/манипулировать кодом
(fn [...] ...)
, поскольку #()
является макросом читателя, а не регулярной формой Clojure.
-
#()
более кратким. Но если это серьезное соображение, вы, вероятно, ошибаетесь в своих приоритетах: -)
Лично мой совет:
- Предпочитает
(fn [...] ...)
в большинстве случаев
- Используйте
#()
только для очень коротких встроенных функций, например. (map #(+ 2 %) (range 10))
- Также подумайте, что лучше генерировать анонимные функции через функции более высокого порядка, а не записывать их явно, например.
(comp func1 func2)
или (partial func param1 param2)
и т.д.
Ответ 2
Другой ответ SO (Ошибки общего программирования для разработчиков Clojure, чтобы избежать) упоминает, что #([% %])
расширяется до fn [%] ([% %])
(обратите внимание на круглые скобки), что вызывает исключение ArityException.
Вы можете сделать #(vector % %)
, чтобы обойти это ограничение.
Ответ 3
Из docs, я думаю, что это наиболее важные отличия:
используется идиоматика для очень короткого однократного отображения/фильтра fns и т.п.
#() формы не могут быть вложенными.
Другое дело, что если вам нужны именованные параметры, fn - лучший вариант. Для #() вы будете использовать% или, для более одного параметра, что-то вроде% 1,% 2 и т.д. (Также% &).