Сегодня мы наткнулись на проблему в нашем коде и не смогли ответить на этот вопрос 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. Из-за этого может быть очень сложно рассуждать о коде и выяснять, что произойдет.
Дополнительные вопросы: