params => positional-params* , or positional-params* & next-param
positional-param => binding-form
next-param => binding-form
name => symbol
Defines a function
;; simple anonymous function passed to (map )
user=> (map (fn [x] (* x x)) (range 1 10))
(1 4 9 16 25 36 49 64 81)
;; anonymous function with a name. not so anonymous now is it?
;; this is useful in stack traces
(fn add[a b] (+ a b))
;; anonymous function with two params, the second is destructed
user=> (reduce (fn [m [k v]] (assoc m v k)) {} {:b 2 :a 1 :c 3})
{2 :b, 1 :a, 3 :c}
;; define and instantly call an anonymous function
user=> ((fn [a b c] (+ a b c)) 2 4 6)
12
;; define and instantly call an anonymous variadic function
;; "nums" is a list here
user=> ((fn [& nums] (/ (apply + nums) (count nums))) 1 2 3 4)
5/2
;; define and instantly call an anonymous mixed function
;; "nums" is a list, while "int" is a number
user=> ((fn [int & nums] (+ int (/ (apply + nums) (count nums)))) 10 1 2 3 4)
25/2
;; define and instantly call an anonymous overloaded function
;; even though it is quite pointless
user=> ((fn ([a] (inc a)) ([a b] (+ a b))) 3)
4
;; the shortcut form for (fn ) is #( ) ;; where parameters are referred by their index with the prefix % ;; the equivalent of user=> ((fn [a b c] (+ a b c)) 2 4 6) 12 ;; is user=> (#(+ %1 %2 %3) 2 4 6) 12
(defmacro fn
"params => positional-params* , or positional-params* & next-param
positional-param => binding-form
next-param => binding-form
name => symbol
Defines a function"
{:added "1.0", :special-form true,
:forms '[(fn name? [params* ] exprs*) (fn name? ([params* ] exprs*)+)]}
[& sigs]
(let [name (if (symbol? (first sigs)) (first sigs) nil)
sigs (if name (next sigs) sigs)
sigs (if (vector? (first sigs)) (list sigs) sigs)
psig (fn* [sig]
(let [[params & body] sig
conds (when (and (next body) (map? (first body)))
(first body))
body (if conds (next body) body)
conds (or conds (meta params))
pre (:pre conds)
post (:post conds)
body (if post
`((let [~'% ~(if (< 1 (count body))
`(do ~@body)
(first body))]
~@(map (fn* [c] `(assert ~c)) post)
~'%))
body)
body (if pre
(concat (map (fn* [c] `(assert ~c)) pre)
body)
body)]
(maybe-destructured params body)))
new-sigs (map psig sigs)]
(with-meta
(if name
(list* 'fn* name new-sigs)
(cons 'fn* new-sigs))
(meta &form))))
Comments top
No comments for fn. Log in to add a comment.