lazy-seq in Clojure (翻訳)

user> (def fib-seq
(lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))

;; => #'user/fib-seq
user> (def fib-seq (concat (lazy-seq [0 1]) (lazy-seq (map + (rest fib-seq) fib-seq))))
;; => #'user/fib-seq
user> (doall (take 2000 fib-seq))

内部のしくみ:

lazy-seq はアクセスされて初めて、一度だけbodyを実行する

例に戻る:

[0 1] はこの問題の基本ケースである。フィボナッチ数列の最初2つの値は0と1である。それぞれの値の連続する計算結果は1つ前の値、もう1つ前の値の合計である。そのため、計算プロセスを始めるために少なくとも2値必要である。

user> (def fib-seq-temp [0 1 1 2 3])
user> (map + (rest fib-seq-temp) fib-seq-temp)
;; => (1 2 3 5)
user> (map + (rest [0 1]) [0])
;; => (1)
user> (map + (rest [0 1]) [1])
;; => (2)
user> (def fib-seq
(lazy-cat [0 1]
(map
(fn [a b]
(println (format "%d + %d" a b)
(+ a b))
(rest fib-seq) fib-seq)))
;; => #'user/fib-seq
user> (doall (take 10 fib-seq))
1 + 0
1 + 1
2 + 1
3 + 2
5 + 3
8 + 5
13 + 8
21 + 13
;; => (0 1 1 2 3 5 8 13 21 34)

lazy-seq マクロ

シーケンスを生成する計算を貯めておくためのthunkを使っている。

シーケンスの先頭を保持する

ランダムな無限の遅延シーケンスを生成するために2つの方法がある

user> (defn infinite[] (lazy-seq (cons (rand) (infinite))))
;; => #'user/infinite
--user> (defn infinite-1[] (lazy-seq (cons (rand) (infinite-1))))
;; => #'user/infinite-1
user> (def zyx (infinite-1))

lazy-seq の重要点

lazy-seq は遅延シーケンスを生成する数多くの方法のうちの1つである。clojureだと、様々な方法で遅延シーケンスを生成できる。

参考:

https://purelyfunctional.tv/lesson/what-are-lazy-sequences/
http://theatticlight.net/posts/Lazy-Sequences-in-Clojure/
http://www.thesoftwaresimpleton.com/blog/2014/09/08/lazy-seq/

--

--

Software engineer

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store