[英]clojure update value during doseq
在doseq期間更新/計算變量的最佳方法是什么?
顯然,我可以執行以下操作:
(doseq [x xs]
(println (string/join " " x)))
(println "total:" (reduce + 0 (map count xs)))
但是我想避免必須在最后映射整個列表來計算值...在迭代時只更新一個計數更有意義。
我發現這很有效 ,但似乎有點麻煩。
(defn display-xs [xs]
;; all I want to do is update a count while I print,
;; and have that value available afterwards!
(let [n (ref 0)]
(do
(doseq [x xs]
(dosync
(ref-set n (+ @n (count x)))
(println (string/join " " x))))
(println "total:" @n))))
我知道doseq
允許:let
但是我需要在doseq完成之后的值。
要么
(println "total:" (reduce (fn [m x] (do (println x) (+ m (count x)))) 0 xs))
您不必擔心循環的最小開銷。 分離不同的任務更為重要。 我非常喜歡您的第一個版本。
您的第二個版本可能看起來更好,但我仍然希望第一個版本。
(defn display-xs [xs]
(let [n (atom 0)]
(doseq [x xs]
(swap! n + (count x))
(println (string/join " " x)))
(println "total: " @n)))
我稍微重寫了您的代碼,所以請展示我該怎么做:
(def sample-vals (repeatedly 10 #(range (+ 5 (rand-int 10)))))
(defn display-xs [xs]
(let [n (atom 0)]
(doseq [x xs]
(swap! n + (count x))
(println x))
(println "total:" @n)))
(newline)
(display-xs sample-vals)
(defn print-n-sum [cum coll]
(let [cnt (count coll) ]
(printf "%4d: " cnt)
(println coll)
(+ cum cnt)))
(defn calc-sum [xs]
(let [n (reduce print-n-sum 0 xs) ]
(println "total:" n)))
(newline)
(calc-sum sample-vals)
結果
> rs; lein run
(0 1 2 3 4 5 6 7 8 9)
(0 1 2 3 4 5 6 7 8 9 10 11)
(0 1 2 3 4 5 6 7 8 9 10)
(0 1 2 3 4 5 6 7 8 9 10 11)
(0 1 2 3 4)
(0 1 2 3 4 5 6 7 8 9 10 11)
(0 1 2 3 4 5)
(0 1 2 3 4 5 6 7 8 9 10)
(0 1 2 3 4 5 6)
(0 1 2 3 4 5 6 7 8 9 10)
total: 97
10: (0 1 2 3 4 5 6 7 8 9)
12: (0 1 2 3 4 5 6 7 8 9 10 11)
11: (0 1 2 3 4 5 6 7 8 9 10)
12: (0 1 2 3 4 5 6 7 8 9 10 11)
5: (0 1 2 3 4)
12: (0 1 2 3 4 5 6 7 8 9 10 11)
6: (0 1 2 3 4 5)
11: (0 1 2 3 4 5 6 7 8 9 10)
7: (0 1 2 3 4 5 6)
11: (0 1 2 3 4 5 6 7 8 9 10)
total: 97
請注意,您不必使用原子(此示例比ref簡單)。 您可以進行打印和添加諸如print-n-sum
類的單個功能,然后將其饋送給reduce
。
您可以在您的reduce append函數中打印它
(defn print-and-append [acc x]
(println (string/join " " x))
(+ acc (count x)))
(println (reduce print-and-append 0 xs))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.