Custom map function behaves oddly in lazy scenarios
为了好玩,我决定编写自己的
1 2 3 4 5 | (defn my-map [f [head & tail]] (lazy-seq (if head (cons (f head) (my-map f tail)) tail))) |
它可以工作,但是当我针对
1 2 3 4 5 6 7 | (defn print-map [description-str f coll mapping-f] (mapping-f (fn [x] (do (print (str description-str":" x)) (f x))) coll)) |
当我使用标准
1 2 3 4 5 6 | (defn -main [] (let [m map coll (into '() (range 10 0 -1)) coll2 (print-map"A" identity coll m) coll3 (print-map"B" identity coll2 m)] (println (doall coll3)))) |
打印:
1 | A:1 B:1 A:2 B:2 A:3 B:3 A:4 B:4 A:5 B:5 A:6 B:6 A:7 B:7 A:8 B:8 A:9 B:9 A:10 B:10 (1 2 3 4 5 6 7 8 9 10) |
请注意两个函数如何处理每个数字,然后才能看到其余元素。
但是当我将
1 | A:1 A:2 B:1 A:3 B:2 A:4 B:3 A:5 B:4 A:6 B:5 A:7 B:6 A:8 B:7 A:9 B:8 A:10 B:9 B:10 (1 2 3 4 5 6 7 8 9 10) |
现在第一个函数运行两次开始,第二个函数最后连续运行两次,因此映射不再"同步"。
导致这种情况发生的
您在
你可以通过不破坏来避免这种情况:
1 2 3 4 5 6 7 8 9 | (defn my-map [f [x :as xs]] #_(next xs) ;; uncomment to observere similar"broken" behaviour (lazy-seq (if x (cons (f x) (my-map f (rest xs))) (rest xs)))) ;; You can find out what destructing does with this call: (destructure '[[x & r :as xs] numbers]) |
next 不像 rest 那样懒惰。