Skip to content

clojure.core/letfn

View this page on ClojureDocs

Type: macro Added: Clojure 1.0 Examples: 5 Runnable: 1
([fnspecs & body])

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

by nipra on . May have evaluation errors.
by miner on
by sleyzerzon on . May have evaluation errors.
by green-coder on . May have evaluation errors.
by claj on . May have evaluation errors.

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:

(letfn [(my-range [n]
          (when (pos? n)
            (cons n (my-range (dec n)))))]
  (my-range 5))
;;=> (5 4 3 2 1)
but 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


Content from the matching ClojureDocs page, with authors credited on each contribution.