我目前正在使用一个功能
(def mymap {})
(defn function1 [var1 var2 var3 var4 var5]
;calls another functions with all variables.
(function2 var1 var2 var3 var4 var5)
)
Run Code Online (Sandbox Code Playgroud)
但由于这是有更多的参数,我想在调用functions2之前将其转换为地图.
(function2((assoc mymap (keyword var1) var1
(keyword var2) var2
(keyword var3) var3
(keyword var4) var4
(keyword var5) var5 ))
)
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?我们有更好的方法吗(在java中我们直接使用这种情况下的一些对象)
对于一般函数args,我总是按照从最大到最小的顺序排列,无论是大小还是"重要性"(有点主观).
但是,如果你有超过3个args,我更喜欢传递一个包含args和相应关键字名称的地图.
在图珀洛的Clojure库有一些工具,使这个容易.该宏vals->map采用多个变量名称,并构造从(关键字化)变量名称到其值的映射,如:
(let [ctx (let [a 1
b 2
c 3
d 4
e 5]
(t/vals->map a b c d e))]
(is= ctx {:a 1 :b 2 :c 3 :d 4 :e 5})
Run Code Online (Sandbox Code Playgroud)
宏with-map-vals执行相反的操作,将映射值解构为为其键命名的局部变量.它类似于Clojure :keys解构,但在(IMHO)更自然的形式:
(let [{:keys [a b c d e]} ctx] ; Clojure destructing syntax
(is= [a b c d e] [1 2 3 4 5]))
(t/with-map-vals ctx [a b c d e]
(is= [a b c d e] [1 2 3 4 5])
(is= 15 (+ a b c d e)))
(t/with-map-vals ctx [b a d c e] ; order doesn't matter
(is= [a b c d e] [1 2 3 4 5])
(is= 15 (+ a b c d e)))
(t/with-map-vals ctx [b a d] ; can ignore stuff you don't care about
(is= [d a b] [4 1 2]))
(throws?
(t/with-map-vals ctx [a b z] ; throws if key doesn't exist
(println "won't ever get here")))))
Run Code Online (Sandbox Code Playgroud)
如果您嵌套在地图和/或矢量数据,你可以使用更强大destruct和restruct工具.这是一个简短的例子(来自单元测试):
(let [info {:a 1
:b {:c 3
:d 4}}
mania {:x 6
:y {:w 333
:z 666}}]
(t/it-> (t/destruct [info {:a ?
:b {:c ?
:d ?}}
mania {:y {:z ?}}] ; can ignore unwanted keys like :x
(let [a (+ 100 a)
c (+ 100 c)
d z
z 777]
(restruct-all)))
(t/with-map-vals it [info mania]
(is= info {:a 101, :b {:c 103, :d 666}})
(is= mania {:x 6, :y {:w 333, :z 777}})))
Run Code Online (Sandbox Code Playgroud)
如您所见,问号?将导致相应的值被破坏为为相应关键字命名的变量.也可以像这样创建显式变量名:
(dotest
(let [info {:a 777
:b [2 3 4]}
mania [{:a 11} {:b 22} {:c [7 8 9]}]]
(let [z ::dummy]
(t/it-> (t/destruct [info {:a z
:b [d e f]}
mania [{:a ?} BBB {:c clutter}]]
(let [clutter (mapv inc clutter)
BBB {:BBB 33}
z 77
d (+ 7 d)]
(restruct-all)))
(t/with-map-vals it [info mania]
(is= info {:a 77, :b [9 3 4]})
(is= mania [{:a 11} {:BBB 33} {:c [8 9 10]}]))))))
Run Code Online (Sandbox Code Playgroud)
它也适用于混合地图和矢量:
(let [data {:a [{:b 2}
{:c 3}
[7 8 9]]} ]
(t/destruct [data {:a [{:b p}
{:c q}
[r s t]]} ]
(is= [2 3 7 8 9] [p q r s t])))
Run Code Online (Sandbox Code Playgroud)