TL;DR
- 評価する必要があるときだけ評価されるシーケンスを遅延シーケンスと呼び、無限の要素を持つシーケンスも作れる。
repeat、cycle、iterateで遅延シーケンスを作り、first、take、nthで要素を取り出す。無限のシーケンスにrestやlastを使うと処理が終わらない。
内容
評価する必要があるときだけ評価されるシーケンスを、遅延シーケンス(lazy sequence)と呼ぶ。これを使うと、無限の要素を持つシーケンスを、コンピュータをクラッシュさせずに作れる。
repeat
無限の要素を持つシーケンスを作る
repeat 関数を使うと、無限個の要素を持つ遅延シーケンスを作れる。
(def multiverse (repeat "universe"))first を使うと、最初の要素だけを取り出せる。
(first multiverse) ; "universe"take を使うと、最初の要素から指定した数の要素を取り出せる。
(take 5 multiverse)
; ("universe" "universe" "universe" "universe" "universe")ただし、rest を使うと処理が永遠に終わらない。
(rest multiverse)last で最後の要素を取り出そうとしても同じである。
(last multiverse)nth で任意の位置の要素を取り出すことはできる。
(nth multiverse 100) ; "universe"
(nth multiverse 10000) ; "universe"有限の要素を持つシーケンスを作る
repeat に数を指定すると、その数の要素を持つ有限のシーケンスも作れる。
(repeat 5 "universe")このシーケンスに対して、nth に要素がない位置を渡すと例外を投げる。
(nth (repeat 5 "universe") 3) ; "universe"
(nth (repeat 5 "universe") 7)
; java.lang.IndexOutOfBoundsException: null要素の数が有限なので、rest や last を適用できる。
(rest (repeat 5 "universe")) ; ("universe" "universe" "universe" "universe")
(last (repeat 5 "universe")) ; "universe"cycle
cycle は、渡したコレクションの要素を「循環的に」持つ、無限個の要素の遅延シーケンスを作る。
(def multiverse (cycle ["universe" "multiverse"]))このシーケンスは、奇数番目の要素が "universe"、偶数番目の要素が "multiverse" である。first と second 関数を使うと、これを確かめられる。
(first multiverse) ; "universe"
(second multiverse) ; "multiverse"遅延シーケンスなので、任意の位置の要素を取り出せる。
(first multiverse) ; "universe"
(nth multiverse 100) ; "universe"
(nth multiverse 1783) ; "multiverse"
(take 3 multiverse) ; ("universe" "multiverse" "universe")iterate
iterate は副作用を持たない関数 f を引数に取り、x, (f x), (f (f x)), … を要素に持つ遅延シーケンスを作る。たとえば次はすべての整数を昇順に持つ遅延シーケンスである。
(def all-numbers (iterate inc 1))take や nth を使うと、任意の位置の要素やシーケンスを取り出せる。
(nth all-numbers 24) ; 25
(take 10 all-numbers) ; (1 2 3 4 5 6 7 8 9 10)次は を持つ遅延シーケンスである。
(defn squared [num] (Math/pow num, 2))
(def squares (iterate squared 5))(take 3 squares) ; (5 25.0 625.0)