clojure的let参数分解,文档描述的很清楚。比如它举的例子
(let [[a b c & d :as e] [1 2 3 4 5 6 7]] [a b c d e]) ->[1 2 3 (4 5 6 7) [1 2 3 4 5 6 7]]
这个let,使用其它语言的可以把它当作赋值。比如:java的 int i = 0,也有支持多变量赋值的,比如perl的 my ($a $b) = @a (不知对不对,就这个意思)。但是clojure变化更大。上面的例子中,最后赋值的结果就是->后面显示的。
(let [[a b & c :as str] "asdjhhfdas"] [a b c str]) ->[\a \s (\d \j \h \h \f \d \a \s) "asdjhhfdas"]
string也一样,在clolure里面不都是seq嘛。
(let [{a :a, b :b, c :c, :as m :or {a 2 b 3}} {:a 5 :c 6}] [a b c m]) ->[5 3 6 {:c 6, :a 5}]
上面是解构map,:or的意思是,如果没有找到,就用默认,:b显然不在{:a 5 :c 6}中,所以最后的值是3。
函数参数的解构:
一般来说函数在定义的时候会指定参数,比如下面的参数,根据显示你呼叫该函数时参数的个数,我这里写到最多接收2个参数,根据Clojure文档描述,最多可以有20个参数(仅仅只这种显式申明的方式)。
(defn- fixargs ([] 0) ([_] 1) [_ _] 2))
如果你执行(fixargs :a :b :c),就会报错。当然我可以这样定义函数:这样不管你传入几个参数,这个函数都会将个数显示出来。但是至少需要2个参数,小于两个参数就会报错。如果把a b 删除,就可以接受任意(包括没有)个数了。
(defn- anyargs [a b & c] (+ 2 (count c)))
如果你偶尔看到下面这种类型的函数参数定义,可能会觉得困惑,不过clojure可以repl,所以测试一下就知道结果了。
(defn- hashp-p [a & {:b b}] [a b])
(hash-p 1 :b 2) --------------> [1 2]
也就是说,你传入3个参数,a娶了第一个1,剩下2个是 :b 2,可见clojure将剩下的2个组成了一个map,对应解构出来就是2了。
如果你认为 [& c]会自动将vector变成map,那就又错了,让我们试一下。
(defn f-n [& c] (:b c)) ;然后呼叫 (f-n :b 2) ---------->nil
clojure的代码咋一看毫无章法,习惯之后,它其实遵循非常简单统一的原则,都是form,求值,就这么两回事。(当然,就像Clojure文档中提到的,它持一种务实的态度,因此引入var,ref,atom,agent等,用相对自然的方式解决对应问题)