Alf*_*oli 3 macros clojure map
我们应该知道,Clojure map可以应用于一个序列:
(map #(* %1 %1) [1 2 3]) ; (1)
Run Code Online (Sandbox Code Playgroud)
..或多个,以这种方式:
(map vector [0 1] [2 1]) ; (2)
;=> ([0 2] [1 1])
Run Code Online (Sandbox Code Playgroud)
现在我想获得与(2)相同的结果,但我将参数存储在序列中.换句话说,以下内容未给出所需的结果:
(map vector [[0 1] [2 1]]) ; (3)
;=> ([[0 1]] [[2 1]])
Run Code Online (Sandbox Code Playgroud)
所以我写了这个简单的宏,其中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))
Run Code Online (Sandbox Code Playgroud)
显然它就像一个魅力:
(umap vector [[0 1] [2 1]]) ; (4)
;=> ([0 2] [1 1])
Run Code Online (Sandbox Code Playgroud)
所以这是我的问题:我是否重新发明轮子?还有另一种方法可以像(4)那样做吗?
再见,谢谢你,
阿尔弗雷多
dfa*_*fan 13
apply 解包参数列表末尾序列中的所有元素.
user> (apply map vector [[0 1] [2 1]])
([0 2] [1 1])
Run Code Online (Sandbox Code Playgroud)
你的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]
Run Code Online (Sandbox Code Playgroud)
宏只能访问符号, args因为它在编译时运行,并且无法拼接它以便使用map.正确的答案是使用apply,它将其最后一个参数视为一个序列,并将其拼接成给定函数的一系列附加参数:
user> (let [args [[1 2] [1 2]]]
(apply map vector args))
([1 1] [2 2])
Run Code Online (Sandbox Code Playgroud)