私は次のように書いた:
(fn r [f xs]
(lazy-seq
(if (empty? xs)
'()
(cons (f (first xs)) (r f (rest xs))))))
4clojure.com の問題 #118 を解決するには: http://www.4clojure.com/problem/118
マップなどを使用せずにマップを再実装するように要求し、そのソリューションはテストに合格します(それが正しいかどうかはわかりません。他のソリューションに非常に近いです)。
問題は怠惰でなければならないと述べていたので、私の解決策をlazy-seqで「ラップ」して上記のコードを書きました...しかし、lazy- seqがどのように機能するかわかりません。
ここで「怠け者」とは何か、またそれをテストする方法がわかりません。
私が尋ねる(type ...)
と、当然のことながら、clojure.lang.LazySeqが得られますが、それと単にレイジー seqの「ラッピング」を削除した場合に得られるものとの違いは何なのかわかりません。
もちろん、lazy-seq を削除すると、これを実行しようとする理由でスタック オーバーフローが発生します。
(= [(int 1e6) (int (inc 1e6))]
(->> (... inc (range))
(drop (dec 1e6))
(take 2)))
それ以外の場合 (つまり、lazy-seq ラッピングを適切に行えば)、問題なく動作するようです。
そこで、どういうわけか「デバッグ」/何が起こっているのかを追跡して、すべてがどのように機能するかを理解しようとすることにしました。次のマクロを使用しました (SO IIRC で見つけました)。
(defmacro dbg [x] `(let [x# ~x] (println "dbg: " '~x "=" x#) x#))
そして、作業バージョンをdbgマクロ内にラップし、再度実行しようとしました。そして今、kaboom: 正常に動作していたバージョンでも、stackoverflow がスローされるようになりました。
今はよくわかりません: マクロの望ましくない効果で、他の方法では評価されないものの評価を何らかの形で強制するのでしょうか?
この単純な関数と単純なテストを使用して、ここで遅延がどのように機能するか、正確には何が呼び出されるかなどを誰かが説明できれば素晴らしいと思います.