Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: named anonymous function

Tags:

clojure

In Clojure, when and why does one want to use a named anonymous function? E.g.,

((fn add-five [x] (+ x 5)) 3))

In ClojureDocs, one example's comment says that it is useful in stack traces. Can one give an example of that?

like image 283
blackened Avatar asked Jan 16 '17 19:01

blackened


2 Answers

There are two reasons to name anonymous functions (or at least two reasons that I've done so). The first is that giving it a name tells a later reader (perhaps yourself 6 months down the line) what the heck that anonymous function is supposed to do.

The second is (as you mention) to have better information in a stack trace to point you at the right location in your code when a failure occurs. Functions are compiled into classes and the class name includes a (munged) version of the function name. When you have a stack trace, it will include that class name and thus point you semantically towards the proper location.

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)
    ...
like image 91
Alex Miller Avatar answered Sep 22 '22 11:09

Alex Miller


Apart from being useful in stacktraces, I suppose you could use it when you need an anonymous function to be recursive, as it would be able to call itself.

For instance:

(fn factorial[n]
  (if (<= n 1)
    1
    (* n  (factorial (- n 1)))))

Although recursing like this in Clojure is a bit dangerous, as it could potentially cause stack overflows.

like image 38
phss Avatar answered Sep 18 '22 11:09

phss