Clojureの怠lazは、Java/Impure Codeへの呼び出しとどのように相互作用しますか?
-
27-10-2019 - |
質問
私たちは今日、私たちのコードの問題に出くわしましたが、このクロジュアの質問に答えることができませんでした。
Clojureは不純なコード(またはJavaコードへの呼び出し)を厳密にまたは怠zileに評価しますか?
副作用 +怠zyなシーケンスは奇妙な動作につながる可能性があるようです。
これが私たちが知っていることが質問につながったことです。
Clojureには怠zyなシーケンスがあります:
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オブジェクトを呼び出すことができます。これには、副作用が含まれる場合があります。ただし、副作用は怠zyな評価とは不十分に相互作用する可能性があります。
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は厳格な評価を実行しますか? (はい?)
解決
Clojureの怠zyなSEQチャンクは約30アイテムであるため、小さなオーバーヘッドがさらに減少します。それは純粋主義者の選択ではなく、実用的なものです。通常のソリューションについては、時間に1つの要素を実現するために、「Clojureの喜び」を参照してください。
怠zyなSeqは、遭遇した理由のために不純な機能にぴったりではありません。
Clojureは厳密に評価しますが、マクロでは物事は少し異なります。などのビルドン if
自然に評価を保持します。
他のヒント
怠zyな構造は、実装に何が参照されていても、実装に便利な場合は多かれ少なかれ評価されます。したがって、はい、必要に応じて慎重に怠zyなSEQを強制的に実現するのはプログラマー次第です。
厳格な評価とはどういう意味かわかりません。