clojure.core/letfn¶
fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+)
Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body.
Examples¶
Note by Justinus¶
Using letfn allows you to create local functions that reference each other whereas (let myfunc #(...)]...) wouldn't because it executes its bindings serially.
Note by reborg¶
To be more precise (about the note above), letfn allows ahead-of-definition use of functions. The following is ok:
(defn testme []
(let [twice (fn [x] (* x 2))
six-times (fn [y] (* (twice y) 3))]
(println "15x6=" (six-times 15))))
But this one for instance doesn't compile (and would be ok with letfn):
(defn testme []
(let [twelve-times (fn [x] (* (six-times x) 2))
six-times (fn [y] (* y 6))]
(println "2x12=" (twelve-times 2))))
Note by muhuk¶
(letfn [(six-times [y]
(* (twice y) 3))
(twice [x]
(* x 2))]
(println "Twice 15 =" (twice 15))
(println "Six times 15 =" (six-times 15)))
;; Twice 15 = 30
;; Six times 15 = 90
;;=> nil
Note by mars0i¶
And just to clarify further what is already implicit in other remarks, letfn allows a definition to refer to itself recursively:
let doesn't:
(let [my-range (fn [n]
(when (pos? n)
(cons n (my-range (dec n)))))]
(my-range 5))
Syntax error compiling at ...
Unable to resolve symbol: my-range in this context
Note by miner¶
This is a bit of tangent, but the fn form optionally takes a name, which allows recursive calls. You still need leftn for mutually recursive functions.
(let [my-range (fn my-range [n]
(when (pos? n)
(cons n (my-range (dec n)))))]
(my-range 5))
;;=> (5 4 3 2 1)
See also¶
- clojure.core/let (7)
- clojure.core/fn (3)
- clojure.core/loop (10)
Content from the matching ClojureDocs page, with authors credited on each contribution.