我们应该知道,Clojure的map
可以应用于序列:
(map #(* %1 %1) [1 2 3]) ; (1)
..或以多种方式,以这种方式:
(map vector [0 1] [2 1]) ; (2)
;=> ([0 2] [1 1])
现在我想获得与(2)相同的结果,但我将参数存储在序列中。换句话说,以下内容未给出所需的结果:
(map vector [[0 1] [2 1]]) ; (3)
;=> ([[0 1]] [[2 1]])
所以我写了这个简单的宏,其中umap代表“unsplice map”:
(defmacro umap [fun args-list]
"umap stands for unspliced map.
Let args-list be a list of args [a1 a2 ... an].
umap is the same of (map fun a1 a2 .. an)"
`(map ~fun ~@args-list))
显然它就像一个魅力:
(umap vector [[0 1] [2 1]]) ; (4)
;=> ([0 2] [1 1])
所以这是我的问题:我是否重新发明轮子? 还有另一种方法可以像(4)那样做吗?
再见,谢谢,
阿尔弗雷
答案 0 :(得分:13)
apply
解包参数列表末尾序列中的所有元素。
user> (apply map vector [[0 1] [2 1]])
([0 2] [1 1])
答案 1 :(得分:8)
你的umap
就像魅力一样,显然并不明显。事实上,只有在编译时将参数向量作为文字时才会起作用 - 这正是你可以将多个参数传递给map
的时间!
user> (umap vector [[1 2] [1 2]])
([1 1] [2 2])
user> (let [args [[1 2] [1 2]]]
(umap vector args))
java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
[Thrown class java.lang.RuntimeException]
宏只能访问符号 args
,因为它在编译时运行,并且无法拼接它以使用map。正确的答案是使用apply
,它将其最后一个参数视为一个序列,并将其拼接成给定函数的一系列附加参数:
user> (let [args [[1 2] [1 2]]]
(apply map vector args))
([1 1] [2 2])
答案 2 :(得分:0)
我是否遗漏了某些内容,或mapcat是否符合您的需求?