我正在使用函数
(def mymap {})
(defn function1 [var1 var2 var3 var4 var5]
;calls another functions with all variables.
(function2 var1 var2 var3 var4 var5)
)
但是由于它具有更多参数,因此我想在调用function2之前将其转换为映射。
(function2((assoc mymap (keyword var1) var1
(keyword var2) var2
(keyword var3) var3
(keyword var4) var4
(keyword var5) var5 ))
)
这是正确的方法吗?我们是否有更好的方法来做到这一点(在Java中,在这种情况下我们不使用某些对象)
答案 0 :(得分:5)
对于一般函数args,我总是按从大到小的顺序排列, 大小或“重要性”(有点主观)。
但是,如果您有3个以上的参数 ,我希望传递包含参数和适当的关键字名称的映射。
Tupelo Clojure library有一些工具可以简化这一过程。宏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})
宏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")))))
如果您在地图和/或矢量中嵌套了数据 ,则可以使用功能更强大的destruct
和restruct
工具。这是一个简短的示例(from the unit tests):
(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}})))
如您所见,问号?
将导致相应的值被分解为以相应关键字命名的变量。也可以像这样创建显式变量名:
(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]}]))))))
它也适用于混合地图和矢量:
(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])))