2012-12-05 20 views
5

私は、遅延作業とキャッシュがどのように機能しているかを非常に理解しています。lazy-seqの段階的な例

私は、作業中のlazy-seqのステップバイステップの例が本当に役立つと思います。たとえば、私は、次の質問を読んだ:

Clojure lazy sequence usage

をそれはまだ明確ではありません。

私の質問は、別のコールがキャッシュされたコールと "等しい"かどうか、コールがどのように判断し、キャッシュにどれくらい滞在するかということです。私は(source lazy-seq)にしようとしましたが、明らかにJavaの土地にありますので、私はここで運が尽きます。

単純なlazy-seqでは、1つの引数(2の累乗のリストなど)を取ると、5と8を呼び出すとどうなりますか?これらの2つの値だけがキャッシュされていますか?

そして、私が既に遅延関数と呼んでいたすべての入力をキャッシュすることによってメモリを破壊しようとすると、無限のリストを作成してキャッシュするのは何ですか?

これは、それ以降のすべての呼び出しで結果がキャッシュされていると言われているからです。キャッシュされている '1' の引数になる2:

1引数であるために発生 '2' を3にキャッシュされた:引数がされてキャッシュされた3 '' の結果... 2 30:I が2にカウントアップ 30これは私が怠け者だから大丈夫ですが、今は メモリに2 ** 30のキャッシュがあり、これまでのすべての呼び出しをすべてキャッシュします。 以降の呼び出し。

またはキャッシュされた最後の呼び出しですか?

ツリーを引数としてレイジー関数を書くとどうなりますか?それはと同じですか?新しい評価が必要かどうかを知るために、引数のが渡されますか?

この動作は、実行時に何らかの形でトレースできますか?

答えて

8

遅延配列の 'cache'は、Webアプリケーションで使用するように期限切れになる変更可能なキャッシュではありません。サイズ1のキャッシュであり、リスト内の各セルに1つずつあります。 'cache'には値が含まれているか、値を計算するためのコードが含まれています。いったん値を計算すると、そのセル/エントリ内の値がキャッシュされ、誰かがセルをもう一度読み込むと、コードを呼び出す代わりに値が直接与えられます。ここで

点を説明するための簡略化され虚REPLセッションである:この例では

user> (def a (range)) 
a = [code-for-rest] 
user> (first a) 
a = [code-for-first, code-for-rest] 
a = [0, code-for-rest] 
result=> 0 
user> (first a) 
a = [0, code-for-rest] 
result=> 0 
user> (nth a 10) 
a = [0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9, code-for-rest] 
result=> 4 

各セルは最初に含まれ(これはちょうどこの点を説明するための簡略化である)の値とを生成するためのコード残りのリストを生成するコードです(リストの最後であればnil)。そのセルが実現されると(レイジーでない場合)、セルの内容が実際の値に置き換えられ、残りのシーケンスを生成するための値とコードが含まれます。リスト内の次のセルが読み込まれると、それは最初に(セルに含まれているように)コードのために生成され、その後、新しいセルのcode-for-nthがそのセルの値を生成します。

+0

+1、どうもありがとう... "intertwinned" の場合に起こる遅延関数を呼ん(たとえば、「nth a 50」、「nth a 100」、「nth a 80」、「nt h 150 ")?そして、そのスレッドへの呼び出しはどうなりますか?各スレッドはサイズ1のキャッシュを持っていますか? –

+0

@CedricMartin Lazy seqsは他のすべてのClojureデータ構造と同様に不変であり、スレッドセーフなので、一度計算されると、格納された値はすべてのスレッド間で共有されます。それはリンクされたリストへのポインタ(それはまさにそれが何であるか)として怠惰なseqを考えるのを助けるかもしれません、リストの末尾だけ誰かがそれを求めるまで、次のポインタの計算を気にしません。 – Alex

+0

'キャッシュ'は文字通りリストのセルにあります。特定のスレッドには関連付けられていません。 –

1

ここでは、実行時に何が起こっているかを示しおもちゃの例があります。出力があるべき

(defn times-two[number] 
(print "- ") 
(* 2 number)) 

(def powers-of-two (lazy-cat [1 2] (map times-two (rest powers-of-two)))) 

(println (take 10 powers-of-two)) 
(println (take 12 powers-of-two)) 

を:

(1 - 64から2 - 4から8 - 16から32 - 128から256 512)

(1 2 4 8 16 32 64 128 256から512 - 1024個の2048)

関連する問題