为了把它放在上下文中,我将把它包装在一个示例函数中:
user> (defn foo [client-opts
table
& [{:keys [attr-conds
last-prim-kvs
span-reqs
return
limit
total-segments
filter-expr
segment return-cc?]
:as opts
:or {span-reqs {:max 5}}}]]
(println "client-opts")
(clojure.pprint/pprint client-opts)
(println "table")
(clojure.pprint/pprint table)
(println "opts")
(clojure.pprint/pprint opts)
(println "the symbol attr-conds is bound to:" attr-conds)
(println "the symbol limit is bound to:" limit)
(println "the symbol span-reqs is bound to:" span-reqs))
#'user/foo
user> (foo :I'm-a-client-opt
:I'm-a-table
{:attr-conds 1
:span-reqs [1 2 3]
:limit 47}
{:attr-conds :i-will-be-ignored}
{:limit :i-will-also-be-ignored})
client-opts
:I'm-a-client-opt
table
:I'm-a-table
opts
{:attr-conds 1, :span-reqs [1 2 3], :limit 47}
the symbol attr-conds is bound to: 1
the symbol limit is bound to: 47
the symbol span-reqs is bound to: [1 2 3]
nil
现在我们看到它将一些名称绑定到列表中第一个映射的部分,所以让我们把这个破坏性表达式分开:
& ;; this symbol collects all the rest of the arguments into a list
[ ;; this one then does list destructuring on the list indicated by the &
{:keys [attr-conds ;; This block destructures the first (and only the first) entry in the vector.
last-prim-kvs ;; Because this is a map it will do map destructuring and
span-reqs ;; bind (assigns) values to symbols in this list
return
limit
total-segments
filter-expr
segment return-cc?]
:as opts ;; the entire map in the first position in the list created by the & will be bound to the name opts
:or {span-reqs {:max 5}}}] ;; if span-reqs is not in the map at all,
;; then the map {:max 5} will be bound to the name
;; span-reqs instead
因此,如果函数的第三个参数是一个不为关键字 :span-reqs 提供值的映射,则该嵌套解构表达式中的关键字 :or 会为符号分配默认值。如果关键字 :span-reqs 存在并且包含其他键但没有为 :max 提供值,则它什么也不做。它确实不在这种情况下将默认值合并到地图中,如果它完全丢失,它只会提供一个值:
这是根本没有指定的值:
user> (foo :I'm-a-client-opt
:I'm-a-table
{:attr-conds 1
;; :span-reqs [1 2 3] ;; removed this one
:limit 47}
{:attr-conds :i-will-be-ignored}
{:limit :i-will-also-be-ignored})
client-opts
:I'm-a-client-opt
table
:I'm-a-table
opts
{:attr-conds 1, :limit 47}
the symbol attr-conds is bound to: 1
the symbol limit is bound to: 47
the symbol span-reqs is bound to: {:max 5}
nil
再次指定一个值,其中该值不包括 :max
user> (foo :I'm-a-client-opt
:I'm-a-table
{:attr-conds 1
:span-reqs {:min -7} ;; present but contains something else
:limit 47}
{:attr-conds :i-will-be-ignored}
{:limit :i-will-also-be-ignored})
client-opts
:I'm-a-client-opt
table
:I'm-a-table
opts
{:attr-conds 1, :span-reqs {:min -7}, :limit 47}
the symbol attr-conds is bound to: 1
the symbol limit is bound to: 47
the symbol span-reqs is bound to: {:min -7}
nil