我试图定义一个函数,它接受一个map和一个常规参数,我想解构map的部分,比如
(defn do-stuff
[[{:keys [foo bar]} where] what]
(println foo bar what))
但是当我调用这个函数时,我得到了一个错误
; Execution error (UnsupportedOperationException) at .../do-stuff (REPL:34).
; nth not supported on this type: PersistentArrayMap
如果我交换函数参数
(defn do-stuff
[what [{:keys [foo bar]} where]]
(println foo bar what))
一切正常。当然,我可以在函数内编写一个let
并在那里进行解构,但我想知道我错过了什么…
编辑澄清一下,我希望能够像
这样调用函数(do-stuff {:foo "something" :bar "something else"} "baz")
既然你没有告诉我们,你的呼叫是什么,我猜是您混淆了用于解构的let
语法功能。
所以下面的调用可以工作——注意在映射的vector中的嵌套和悬垂的where
:
(defn do-stuff
[[{:keys [foo bar]} where] what]
(println foo bar what))
(do-stuff [{:foo 1 :bar 2} 3] 4)
; 1 2 4
(defn do-stuff
[what [{:keys [foo bar]} where]]
(println foo bar what))
(do-stuff 0 [{:foo 1 :bar 2} 3])
; 1 2 0
虽然您不打印where
,但似乎您想要保留地图本身。但这是通过:as
完成的。
(defn do-stuff
[{:keys [foo bar] :as where} what]
(println foo bar where what))
(do-stuff {:foo 1 :bar 2 :baz 3} 4)
; 1 2 {:foo 1, :bar 2, :baz 3} 4
编辑
事情发生的原因可以追溯到:
位置解构适用于字符串(它给出字符on位置,但是映射解构失败,因为char是no地图。但它优雅地失败了,只是将nil
分配给两个键变量。
但是当提供映射时,它会失败,因为它们不能(通过nth
访问),因此出现错误信息。
(defn do-stuff
[[{:keys [foo bar]}]]
(println foo bar))
(do-stuff "baz")
; nil nil
(do-stuff {:foo "something" :bar "something else"})
; throws