Same as (def name (fn [params* ] exprs*)) or (def
name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
to the var metadata
user=> (defn foo [a b c]
(* a b c))
#'user/foo
user=> (foo 1 2 3)
6
user=> (defn bar [a b & [c]]
(if c
(* a b c)
(* a b 100)))
#'user/bar
user=> (bar 5 6)
3000
user=> (bar 5 6 2)
60
user=> (defn baz [a b & {:keys [c d] :or {c 10 d 20}}]
(* a b c d))
#'user/baz
user=> (baz 2 3)
1200
user=> (baz 2 3 :c 5)
600
user=> (baz 2 3 :c 5 :d 6)
180
user=> (defn boo [a b & {:keys [c d] :or {c 10 d 20} :as all-specified}]
(println all-specified)
(* a b c d))
#'user/boo
user=> (boo 2 3)
nil
1200
user=> (boo 2 3 :c 5)
{:c 5}
600
user=> (boo 1 2 :d 3 :c 4)
{:c 4, :d 3}
24
;; You can use destructuring to have keyword arguments. This would be a
;; pretty verbose version of map (in an example a bit more verbose than
;; the first above):
(defn keyworded-map [& {function :function sequence :sequence}]
(map function sequence))
;; You can call it like this:
user=> (keyworded-map :sequence [1 2 3] :function #(+ % 2))
(3 4 5)
;; The declaration can be shortened with ":keys" if your local variables
;; should be named in the same way as your keys in the map:
(defn keyworded-map [& {:keys [function sequence]}]
(map function sequence))
(defn somefn
[req1 req2 ;required params
& {:keys [a b c d e] ;optional params
:or {a 1 ;optional params with preset default values other than the nil default
; b takes nil if not specified on call
c 3 ; c is 3 when not specified on call
d 0 ; d is 0 --//--
; e takes nil if not specified on call
}
:as mapOfParamsSpecifiedOnCall ;takes nil if no extra params(other than the required ones) are specified on call
}]
(println req1 req2 mapOfParamsSpecifiedOnCall a b c d e)
)
=> (somefn 9 10 :b 2 :d 4)
;9 10 {:b 2, :d 4} 1 2 3 4 nil
nil
=> (somefn)
;ArityException Wrong number of args (0) passed to: funxions$somefn ;clojure.lang.AFn.throwArity (AFn.java:437)
=> (somefn 9 10)
;9 10 nil 1 nil 3 0 nil
nil
=> (somefn 9 10 :x 123)
;9 10 {:x 123} 1 nil 3 0 nil
nil
=> (somefn 9 10 123)
;IllegalArgumentException No value supplied for key: 123 ;clojure.lang.PersistentHashMap.create (PersistentHashMap.java:77)
=> (somefn 9 10 123 45)
;9 10 {123 45} 1 nil 3 0 nil
nil
=> (try
(somefn 9 10 123)
(catch IllegalArgumentException e (println "caught:" e)))
;caught: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: 123>
nil
(def
^{:doc "Same as (def name (fn [params* ] exprs*)) or (def
name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
to the var metadata"
:arglists '([name doc-string? attr-map? [params*] body]
[name doc-string? attr-map? ([params*] body)+ attr-map?])
:added "1.0"}
defn (fn defn [&form &env name & fdecl]
(let [m (if (string? (first fdecl))
{:doc (first fdecl)}
{})
fdecl (if (string? (first fdecl))
(next fdecl)
fdecl)
m (if (map? (first fdecl))
(conj m (first fdecl))
m)
fdecl (if (map? (first fdecl))
(next fdecl)
fdecl)
fdecl (if (vector? (first fdecl))
(list fdecl)
fdecl)
m (if (map? (last fdecl))
(conj m (last fdecl))
m)
fdecl (if (map? (last fdecl))
(butlast fdecl)
fdecl)
m (conj {:arglists (list 'quote (sigs fdecl))} m)
m (let [inline (:inline m)
ifn (first inline)
iname (second inline)]
;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...)
(if (if (clojure.lang.Util/equiv 'fn ifn)
(if (instance? clojure.lang.Symbol iname) false true))
;; inserts the same fn name to the inline fn if it does not have one
(assoc m :inline (cons ifn (cons (clojure.lang.Symbol/intern (.concat (.getName ^clojure.lang.Symbol name) "__inliner"))
(next inline))))
m))
m (conj (if (meta name) (meta name) {}) m)]
(list 'def (with-meta name m)
;;todo - restore propagation of fn name
;;must figure out how to convey primitive hints to self calls first
(cons `fn fdecl) ))))
Comments top
No comments for defn. Log in to add a comment.