今天我们在代码中遇到了一个问题,无法回答这个Clojure问题:
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是否执行严格评估?(是的?)