8

今日は我々のコードに問題がつまずいており、このClojureの質問に答えることができませんでした:Clojureの怠惰は、Java /不純なコードへの呼び出しとどのように相互作用しますか?

Clojureのは、不純なコード(またはJavaコードの呼び出し)を評価してい厳密または遅延して?

副作用+遅延シーケンスが奇妙な動作につながる可能性があります。ここで


は、私たちが疑問につながったことを知っているものです:

Clojureのは怠惰なシーケンスがあります。

user=> (take 5 (range)) ; (range) returns an infinite list 
(0 1 2 3 4) 

をそしてClojureのは、副作用や不純な機能を持っています

user=> (def value (println 5)) 
5        ; 5 is printed out to screen 
user=> value 
nil        ; 'value' is assigned nil 

また、Clojureは副作用を含むJavaオブジェクトを呼び出すことができます。 しかし、副作用は、遅延評価と悪い相互作用することができる:

user=> (def my-seq (map #(do (println %) %) (range))) 
#'user/my-seq 
user=> (take 5 my-seq)        
(0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
0 1 2 3 4) 

は、だから、最初の5つの要素を返しますが、最初の31を印刷!

Javaオブジェクトに対して副作用メソッドを呼び出すと、同じ種類の問題が発生する可能性があります。これにより、コードについての理由を突き止め、何が起こるのかが分かりにくくなる可能性があります。


補助質問:

  • は気を付けると、このような事態を防ぐために、プログラマにそれをか?(はい?)
  • Clojureは厳密な評価を実行しますか?(はい?)

答えて

8

Clojureの怠惰なseqsは約30項目をチャンクするので、少しのオーバーヘッドがさらに減少します。純粋主義者の選択ではなく、実用的なものです。 1つの要素を時間で実現するための一般的な解決方法については、「Clojureの喜び」を参照してください。

怠惰なseqsは、あなたが遭遇した理由のために、不純な関数に完全にマッチしません。

Clojureも厳密に評価されますが、マクロでは少し異なります。 ifのようなビルトインは当然評価を保持します。

+2

これは、副作用と怠け者の質問を混ぜ合わせる方法ではありません。これは、「それは奇妙でした。なぜそれが起こったのですか。質問。あなたの答えを以下のように解釈していますか?Clojureは、純粋でない/ Javaの呼び出しを厳密に評価します。プログラマーの責任であり、不純なものと怠け者を混ぜないでください。 –

+3

@MattFenwick、基本的にClojureは常に厳密に評価します。遅れたseqは基本的にpythonと同じトリックをジェネレータなどで使用します。 :) – progo

2

レイジー構造は、参照するものが何であれ、実装が便利なときはいつでも評価されます。ですから、必要に応じて怠惰なseqを実現するように注意し、強制することはプログラマの責任です。

厳密な評価の意味がわかりません。

+0

http://en.wikipedia.org/wiki/Strict_evaluation –

+1

プロゴが述べたように、クローザーは厳密に評価します。 *関数呼び出しとバインディング*。マクロは彼らの議論で好きなことをすることができます。 (Lazy)seqは抽象であり、厳密な/熱心な評価は実際には直接適用されません。怠惰なseqはそれ自身を評価します - あなたがその値が実現していると確信している要素を調べようとするときだけです(それはすでにそれ以前に起こったかもしれませんが)。 –

関連する問題