2011-04-08 51 views
3

我們應該知道,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圖」:

(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 [email protected])) 

顯然它像一個魅力:

(umap vector [[0 1] [2 1]])  ; (4) 
;=> ([0 2] [1 1]) 

所以這裏是我的問題:我是否在重新發明輪子? 還有另外一種方法可以像(4)一樣做嗎?

再見和感謝提前,

阿爾弗雷多

回答

13

apply解壓所有序列中的元素中的參數列表的末尾。

user> (apply map vector [[0 1] [2 1]]) 
([0 2] [1 1]) 
+1

謝謝,我確定我是在重新發明輪子:) – 2011-04-08 16:29:11

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,因爲它運行在編譯時,爲了使用地圖無法接合它。正確的答案是使用apply,它把它的最後一個參數爲一個序列,並將其拼接成一系列的附加參數給定功能:

user> (let [args [[1 2] [1 2]]] 
     (apply map vector args)) 
([1 1] [2 2]) 
+0

感謝amalloy,你的回答總是有用! – 2011-04-08 18:44:47

0

我失去了一些東西,或不適合您的需求mapcat工作?

+0

你一定錯過了一些東西,但我不確定是什麼。 'mapcat'沒有讓他更接近解決他的問題。 – amalloy 2011-04-13 02:38:34

+0

啊,好的。我想我明白我現在失去的東西。 – 2011-04-13 10:07:30

相關問題