2017-01-10 15 views
1

人気のあるオンラインチュートリアルは自然数で構築するために、この例を示します:例えばClojureの怠惰-seqの自然数

(def infseq (map inc (iterate inc 0)))

を、(take 5 infseq)ができます:私は何を見ることができます

1 2 3 4 5

(iterate inc 0)しかし、全体として、私は正確に何が起こっているのか理解していません。 (例えば、これは通常の関数定義ではありません)

誰か説明していただけますか?

+0

実際、これは関数定義ではありません。 '(ifn?infseq)'は 'false'を返します。正確にあなたが理解していないことの詳細を教えてください。それは 'map inc'部分か' def infseq'部分か 'take 5'部分ですか?またはそれらのいくつかの組み合わせ? –

答えて

2

は、その表現を打破のをしてみましょう:

(map inc (iterate inc 0))) 

は、この構造を持つリスト(データ構造)です:

(function-to-call function-passed-as-first-srgument another-list-as-second-arg) 

今度は内側からそれを調べることによって、それを探検しましょう!
その内側のリスト:

(iterate inc 0) 

はこのそれを追跡することによって、無限のシーケンスを作成し

(function-to-call function-passed-as-first-argument number) 
  • 呼び出される関数がiterateあるstrucute、内部の状態、そして毎回新しい価値を持っていますシーケンスを長くする必要がある場合、最初の引数として渡された関数を受け取り、現在の状態で呼び出します。
  • 第一引数として渡された関数は、iterate 1つの
  • 3番目の引数が初期状態であるnumbrと広告をとるincあります。どこから始めるのか。

この内部式が評価されると、実際にそのリストを構築することなく、すぐにリストを表すデータ構造体が返されます。そのリストから最初の値が読み込まれると、最初の値0が返されます.2番目の値が要求されると、inc関数を使用して数値が1になります。最初の値または2番目の値が再度必要な場合は、再計算されずそのまま使用されます。

したがって、最初の引数は、必要な数だけ生成するための契約を表します。これは、元の式の第3引数である。

最初の式はそのレイジーリストを取り、新しいレイジーリストを作成します。

この新しい遅延リストはmap関数によって返されます。

(map inc (0 1 2 3 4 ... as many as you read ...)) 
それは、この配列を生じる読んだ、と一瞬だけで、(実際にはそれが少し速くなるように前方に20かそこらのアイテムをキャッシュする)読んだだけで、これらのそれぞれに incを適用します

((inc 0) (inc 1) (inc 2) (inc 3) ... as much as you read from the sequence ...) 

ということになります:

これらと同等の表現と同じ結果である
(1 2 3 4 ... created lazily) 

(rest (range)) 

(iterate inc 1) 

および他の多くの形態。

+0

良い例ではないことを教えてくれてありがとう –

+0

ありがとう。今私はなぜ私が混乱していたかを見ます。著者は、 '(def infseq(iterate inc 1))'で十分である場合、問題を不必要に長くしました。私は 'マップ'が実際に必要であると思った。なぜなら、マクロ定義ではなく関数定義の観点から考えていたからです(なぜ、おそらく私は概念の初心者です)。 – blackened

1
(take 5 (iterate inc 0)) => (0 1 2 3 4) 

iterateは繰り返しループ内でinc関数を適用します。あなたは[0 1 2 3 ...]

(take 5 (map inc (iterate inc 0))) => (1 2 3 4 5) 

(map inc <collection>)は前回の結果が[1 2 3 4に変換されるまで、コレクション内の各項目に時間後incを適用し得るようにするには、0で始めています。 ..]

(take 5 (range)) => (0 1 2 3 4) 

range/O任意の引数wは0から始まり、永久カウント、実施例1と同じ。

これらのコレクションはすべて無限であるため、印刷する長さを制限するには(take 5 <collection>)のようなものが必要です。

+0

私はまだ理解していません。 (あなたとあなたの説明であなたが言ったことはすでに分かっていますが)私には何かがあります。 – blackened

2

。例の目的のために次のように、我々はmapiterateを定義することができます。

(defn iterate [f init] 
    (lazy-cons init (iterate f (f init)))) 

(defn map [f [x & xs]] 
    (lazy-cons (f x) (map f xs))) 

... lazy-consはそれがなるまで作用していないconsのバージョンです。それはclojure.coreの一部に使用され、このように定義されている可能性があります:

(defmacro lazy-cons [x xs] 
    `(lazy-seq (cons ~x ~xs))) 

これらの定義を理解するには、再帰、怠惰、非構造、およびマクロでグリップを取得する必要があります:かなりの作業!しかし、は、iteratemapを含むclojureのシーケンスライブラリの仕組みを理解しています。それは私が学んだ方法です。


iterateの定義が有効です。 mapのうちの1つは、無限のシーケンス引数に対してのみ機能します。

関連する問題