How does Clojure's laziness interact with calls to Java/impure code?

拥有回忆 提交于 2019-12-23 07:52:35

问题


We stumbled upon an issue in our code today, and couldn't answer this Clojure question:

Does Clojure evaluate impure code (or calls to Java code) strictly or lazily?

It seems that side-effects + lazy sequences can lead to strange behavior.


Here's what we know that led to the question:

Clojure has lazy sequences:

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

And Clojure has side-effects and impure functions:

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

Also, Clojure can make calls to Java objects, which may include side-effects. However, side-effects may interact poorly with lazy evaluation:

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)

So it returned the first 5 elements, but printed the first 31!

I assume the same kinds of problems could occur if calling side-effecting methods on Java objects. This could make it really hard to reason about code and figure out what's going to happen.


Ancillary questions:

  • Is it up to the programmer to watch out for and prevent such situations? (Yes?)
  • Besides sequences, does Clojure perform strict evaluation? (Yes?)

回答1:


Clojure's lazy seqs chunk about 30 items so the little overhead is further reduced. It's not the purist's choice but a practical one. Consult "The Joy of Clojure" for an ordinary solution to realize one element at time.

Lazy seqs aren't a perfect match for impure functions for the reason you encountered.

Clojure will also evaluate strictly, but with macros things are a bit different. Builtins such as if will naturally hold evaluating.




回答2:


Lazy constructs are evaluated more or less whenever is convenient for the implementation no matter what's referenced in them. So, yes, it's up to the programmer to be careful and force realization of lazy seqs when needed.

I have no idea what you mean by strict evaluation.



来源:https://stackoverflow.com/questions/7824501/how-does-clojures-laziness-interact-with-calls-to-java-impure-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!