В Clojure, когда и почему вы хотите использовать анонимную функцию? Например.
((fn add-five [x] (+ x 5)) 3))
В ClojureDocs, один комментарий к примеру говорит, что он полезен в трассировке стека. Можно ли привести пример этого?
В Clojure, когда и почему вы хотите использовать анонимную функцию? Например.
((fn add-five [x] (+ x 5)) 3))
В ClojureDocs, один комментарий к примеру говорит, что он полезен в трассировке стека. Можно ли привести пример этого?
Существует две причины назвать анонимные функции (или по крайней мере две причины, по которым я это сделал). Во-первых, если дать ему имя, то он скажет более позднему читателю (возможно, самому себе через 6 месяцев), что, как предполагается, должно выполнять анонимная функция.
Вторая (как вы упоминаете), чтобы иметь лучшую информацию в трассировке стека, чтобы указать вам в нужном месте в вашем коде при возникновении сбоя. Функции скомпилируются в классы, а имя класса включает (измененную) версию имени функции. Когда у вас есть трассировка стека, она будет включать это имя класса и, таким образом, указывает вам семантически в нужное место.
user=> (filter (fn [x] (/ 100 x)) [100 50 0])
ArithmeticException Divide by zero clojure.lang.Numbers.divide (Numbers.java:158)
user=> (pst *e)
ArithmeticException Divide by zero
clojure.lang.Numbers.divide (Numbers.java:158)
clojure.lang.Numbers.divide (Numbers.java:3784)
user/eval8/fn--9 (NO_SOURCE_FILE:3)
clojure.core/filter/fn--6908 (core.clj:2790)
...
nil
user=> (filter (fn hundred-div [x] (/ 100 x)) [100 50 0])
ArithmeticException Divide by zero clojure.lang.Numbers.divide (Numbers.java:158)
user=> (pst *e)
ArithmeticException Divide by zero
clojure.lang.Numbers.divide (Numbers.java:158)
clojure.lang.Numbers.divide (Numbers.java:3784)
user/eval14/hundred-div--15 (NO_SOURCE_FILE:5) ;; <---
clojure.core/filter/fn--6908 (core.clj:2790)
...
Помимо полезности в stacktraces, я полагаю, вы могли бы использовать его, когда вам нужно, чтобы анонимная функция была рекурсивной, так как она могла бы называть себя.
Например:
(fn factorial[n]
(if (<= n 1)
1
(* n (factorial (- n 1)))))
Хотя рекурсия, подобная этой в Clojure, немного опасна, поскольку она потенциально может привести к переполнению стека.
Именованные анонимные функции могут быть полезны, когда они ссылаются на себя, а также печатаются с их именем:
user=> ((fn [] (throw (Exception. "unnamed"))))
Exception unnamed user/eval805/fn--806 (NO_SOURCE_FILE:1)
user=> ((fn myfn [] (throw (Exception. "named"))))
Exception named user/eval809/myfn--810 (NO_SOURCE_FILE:1)