2012-07-23 56 views
6

爲什麼這一點的Clojure代碼:Clojure的不斷和地圖功能

user=> (map (constantly (println "Loop it.")) (range 0 3)) 

產量輸出:

Loop it. 
(nil nil nil) 

我希望它打印出「循環播放」三倍側三次評估功能的效果。

回答

9

constantly不評估其參數多次。這是一個函數,而不是一個宏,因此在運行constantly之前,參數只被計算一次。所有constantly確實是需要的(評價)的說法,並返回每次被稱爲時間返回給定值的函數(無需重新評估什麼,因爲,正如我所說,constantly運行之前的說法已經被評估)。

如果您只想對該範圍內的每個元素調用(println "Loop it"),則應該將其作爲映射函數傳遞,以代替constantly。請注意,您實際上必須將其作爲函數傳遞,而不是評估表達式。

+0

瞥源。這看起來像贏家。 – Mike 2012-07-23 13:10:45

+0

試圖不斷使用,以避免顯式傳遞我不需要的參數。雖然會解決這個問題。 – Mike 2012-07-23 13:18:39

+10

請注意,如果你只是想副作用,你應該使用'doseq'或'dotimes'。由於'map'是懶惰的,除非你用'doall'或'dorun'強制執行,否則你不會得到你想要的結果。 – 2012-07-23 15:18:39

3

你可以通過USIG repeatedly和lambda表達式靠近你的意圖的行爲。

例如:

(repeatedly 3 #(println "Loop it")) 

除非你在REPL,這需要由一個dorun或類似的包圍。 repeatedly是懶惰的。

+0

由於Lambda想要使用傳遞給它的參數,因此不會進行編譯。在這種情況下,我寧願忽略這個論點。 – Mike 2012-07-23 17:17:32

+0

我已經添加了一個使用示例,與您的類似。 – sortega 2012-07-23 20:42:38

+0

哦,這更有意義。謝謝! – Mike 2012-07-24 12:28:25

3

由於sepp2k正確地指出constantly是一個函數,所以它的參數將只計算一次。

慣用的方式來實現,你在這裏做什麼是使用doseq

(doseq [i (range 0 3)] 
    (println "Loop it.")) 

或可替代dotimes(因爲你實際上並沒有使用其在該特定情況下多了幾分簡潔高效)由range產生的序列:

(dotimes [i 3] 
    (println "Loop it.")) 

這些解決方案的兩者都是非延遲,這可能是你想要什麼,如果你是剛剛運行的副作用,一些代碼。