(defn get-vector []
(let [rs (atom [])]
(map (fn [x] (swap! rs conj x)) [1 2 3 4])
@rs))
(get-vector)
この関数は、[1 2 3 4]
を返す必要があります。 しかし、空のベクトル[]
を返します。なぜクロージャースワップ!マップで正しく動作しないのですか?
(defn get-vector []
(let [rs (atom [])]
(map (fn [x] (swap! rs conj x)) [1 2 3 4])
@rs))
(get-vector)
この関数は、[1 2 3 4]
を返す必要があります。 しかし、空のベクトル[]
を返します。なぜクロージャースワップ!マップで正しく動作しないのですか?
Clojure map
は怠け者であり、その結果を求めていないので、その内容は評価されず、swap!
で機能が実行されません。 - これはどのようにswap!
作品をテストするだけのサンプルコードであれば
(defn get-vector []
(let [rs (atom [])]
(dorun (map (fn [x] (swap! rs conj x)) [1 2 3 4]))
@rs))
(get-vector)
;; => [1 2 3 4]
私が解決しようとしている問題を確認していない:それはあなたがdorun
を使用して、その内容を実現することを強制すべき作業得るために
そのコードよりもOKです。それ以外の場合は、reduce
のような別のソリューションを使用して、変更可能な参照を避けることもできます。
@Shlomiによって示唆されるように、副作用のためdoseq
を使用することがより慣用のようになります。
(let [rs (atom [])]
(doseq [x [1 2 3 4]]
(swap! rs conj x))
@rs)
doseq
は、より慣用的ですが、私はmap
の構文を好むので、別のオプションは、maprun
を作成することですこれを実現するためのシーケンスを強制的に:
(def maprun (comp dorun map))
(defn get-vector []
(let [rs (atom [])]
(maprun (fn [x] (swap! rs conj x)) [1 2 3 4])
@rs))
(get-vector)
maprun
は単なるシンタックスシュガーであるように、これは、技術的にPiotrekのと同じです。
この関数は、名前が['run!'](http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/run!)で、すでにコアライブラリの一部であるため。 – glts
'map'は副作用のための慣用句ではなく、[' doseq'](https://clojuredocs.org/clojure.core/doseq) – Shlomi
があります。このようなシナリオでは 'doseq'を使う方が良いでしょう。私は答えを強化しましょう。 –