Clojure China

关于 defn 参数个数的问题

clojure
#1

下面代码片段来自 https://clojuredocs.org/clojure.core/defn

(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 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

问题是 为什么(somefn 9 10 123 45) 这个运行是对的?

测试表明 在(somefn 9 10 123 45) 可以再增加2,4,6,8 个参数,运行也是对的。如

e2.core=> (somefn 9 10 123 45 2 2 3 3 4 4  5 5)
9 10 {4 4, 3 3, 2 2, 5 5, 123 45} 1 nil 3 0 nil
nil

但是如果增加 1,3,5, 7个参数,是有错误的,如

e2.core=> (somefn 9 10 123 45 2 2 3 3 4 4  5 )
Execution error (IllegalArgumentException) at e2.core/somefn (form-init9456135756365268800.clj:1).
No value supplied for key: 5
#2

是 多余的key 作为 key value处理了。

#3

偶数seq解构的时候,可以当成一个key-val对.

user=> (defn f [& args] (let [{:keys [a b] :or {a 1 b 2} :as kv } args ] [a b] ))
#'user/f
user=> (f 1 2 6)
Execution error (IllegalArgumentException) at user/f (REPL:1).
No value supplied for key: 6

user=> (f 1 2 )
[1 2]

1赞