我是否重新发明了(方形)轮子?

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)


ama*_*loy 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]
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)