解构(destructuring)是允许你为某些东西中的元素分配命名绑定。1
初识解构
(let [[集合里元素取的新名字] 解构的集合])
(let [[a b] ["aa" "bb"]]
(println (str "a =" a ";b = " b)))
;;-> a =aa;b = bb
let绑定中值被分配给了a和b。解构其实就是根据绑定表达式中符号的位置来得知要绑定哪个值。如上例子,我们可以很直观的知道a变量被绑定的值为"aa",b变量被绑定的值为"bb"。
解构可以得到更加简明、可读和优雅的代码,针对嵌套也可以容易处理:
(let [[a [b]] ["aa" ["cc"]]]
(println (str "a =" a ";b = " b)))
;;-> a =aa;b = cc
解构延伸
我们也可以使用:as在解构的同时保持最初的数据结构:
(let [[a [b] :as original] ["aa" ["cc"]]]
(println {:a a :b b :original original}))
;;-> {:a aa, :b cc, :original [aa [cc]]}
若映射中没有找到的键,可以使用or指定要用的默认值:
(let [{aa :a bb :b :or {bb "missing"}} {:a "isa"}]
(println (str aa " ; " bb)))
;;-> isa ; missing
注意此时let绑定的是一个映射,同时解构的也是一个映射,由于解构的映射中没有:b所以显示默认值"missing",还需要注意的是在声明绑定的时候,映射的值写在前面键写在后面{aa :a bb :b}。
若我们解构的映射的键和值的名字一样,可以使用:keys指令而不必把键和值都写出来:
(let [{a :a b :b}
{:a "aa" :b "bb"}]
(println (str a " ; " b)))
;;使用:keys指令
(let [{:keys [a b]}
{:a "aa" :b "bb"}]
(println (str a " ; " b)))
;;-> aa ; bb
函数参数上的解构
之前我们的解构是用在绑定参数上,当然在函数参数上也可以使用解构,其用法与绑定参数类似,只不过是解构的格式不同。
(defn example [test]
(println (str "a = " (:a test)
" and "
"b = " (:b test))))
(example {:a "aaa" :b "bbb"})
;;-> a = aaa and b = bbb
同理,我们也可以在example [test]中使用:keys等参数来完成解构。
W3School中有部分解构的例子,可以跟着写一下进一步感受解构。2
注意:本文的例子都是用println打印出的,若你使用的交互式REPL可不需要使用println打印,输入回车后便会显示出结果。
Living Clojure(中文版):中国电力出版社 ↩︎
Clojure解构:https://www.w3cschool.cn/clojure/clojure_destructuring.html ↩︎