雖然我熟悉函數式語言,主要是Scala,但我對Clojure相當陌生。關於Clojure集合的操作
我想弄清楚在Clojure中對集合進行操作的慣用方式是什麼。我對map
等功能的行爲特別困惑。
在Scala中,一個非常小心的做,這樣map
總是會返還相同種類的原始集合的集合,只要這是有道理的:
List(1, 2, 3) map (2 *) == List(2, 4, 6)
Set(1, 2, 3) map (2 *) == Set(2, 4, 6)
Vector(1, 2, 3) map (2 *) == Vector(2, 4, 6)
相反,Clojure中,就我所知,大多數操作(如map
或filter
)都是懶惰的,即使在急切的數據結構上調用時也是如此。這有奇怪的結果
(map #(* 2 %) [1 2 3])
lazy-list,而不是一個向量。
雖然我更喜歡懶惰的操作,但我發現上面的問題很混亂。事實上,媒介保證了列表中沒有的某些性能特徵。
說我使用上面的結果並追加它的結尾。如果我理解正確,結果不會被評估,直到我試圖追加它,然後它被評估,我得到一個列表,而不是一個向量;所以我必須遍歷它才能追加到最後。之後我可以把它變成矢量,但是這會變得混亂,可以被忽略。
如果我理解正確,map
是多態的,實現它不會是一個問題,以便它返回向量上的向量,列表上的列表,流上的流(此時帶有惰性語義)等等。我想我錯過了Clojure及其成語的基本設計。
什麼是Clojure的數據結構的基本操作的原因不preverse結構?
看看地圖的源代碼。地圖不關心集合的類型。您可以在地圖上建立一個記住集合類型的宏,並在最後將集合轉換爲該類型。 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj –
在https://github.com/上查看clojure.algo.generic.functor/fmap保留輸入類型的'map'實現的clojure/algo.generic。 – Alex