我想重複執行一個功能其副作用對一個集合。 的常用方法是:在clojure中,是否有劑量類似的功能,接收功能而不是身體
(defn my-func [x] (println x))
(doseq [x '(1 2 3) ]
(my-func x))
但X變量有點繁瑣。我更喜歡以下代碼:
((comp doall map) my-func '(1 2 3))
您認爲這是一個優雅的解決方案嗎?
我想重複執行一個功能其副作用對一個集合。 的常用方法是:在clojure中,是否有劑量類似的功能,接收功能而不是身體
(defn my-func [x] (println x))
(doseq [x '(1 2 3) ]
(my-func x))
但X變量有點繁瑣。我更喜歡以下代碼:
((comp doall map) my-func '(1 2 3))
您認爲這是一個優雅的解決方案嗎?
clojure.core/dorun
比doall
更好,因爲doall
持有,以便將其返回到您在內存中的整個序列。 dorun
返回nil
,就像doseq
一樣。如果說語言核心「應該」提供類似domap
是有點咄咄逼人 - 爲鼓勵突變和副作用的語言,Clojure中已經有大量的是非常接近你想要什麼,很容易結合的功能。
爲什麼你不寫一個函數,它需要函數和序列,並通過doseq將函數應用到序列中。
例如
user=> (defn doseqf [fun seq] (doseq [x seq] (fun x)))
#'user/doseqf
user=> (doseqf println '(1 2 3))
1
2
3
nil
我其實蠻喜歡:
((comp dorun map) my-func '(1 2 3))
它的Clojure中的「點自由風格」的一個很好的例子。高階函數(comp dorun map)
是潛在有用的其他地方....你可能會命名爲「應用到序列」或類似的東西。
您還可以使用以下(amalloy的建議),它也指出,自由和可能多一點地道:
(dorun (map my-func '(1 2 3)))
但是要注意,使用地圖這兩種解決方案將構建一箇中間(懶惰)序列保存地圖功能的結果。這意味着額外的開銷量小,因此,如果您關心性能話,我想用doseq的標準方式是更好的,即..
(doseq [x '(1 2 3)] (my-func x))
使用doseq
。不要將惰性序列與副作用結合起來。它可能會導致意想不到的結果,例如分塊的序列。
我分享你在地圖的簡潔風格的興趣,我也討厭不必創建在這種情況下臨時變量。
幸運的是,你可以很容易地編寫一個函數自己:
(defn domap
"Implementation of Common Lisp `mapc`. It is like `map` except that the
results of applying function are not accumulated. The `colls` argument
is returned."
[f & colls]
(reduce (fn [_ args]
(apply f args))
nil (apply map list colls))
colls)
現在你有副作用的映射功能:
(domap println '(1 2 3))
這裏大部分是之前寫的答案發布1.7,其中這樣的功能被添加到Clojure中。
該功能是run!
。
(run! f coll)
相當於(dorun (map f coll))
。在Clojure 1.7及更高版本中優先使用run!
。
['run!'](https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/run!)是未來的答案:它被添加到Clojure中版本1.7。 – glts 2017-08-16 17:35:54