Сегодня мы столкнулись с проблемой в нашем коде и не смогли ответить на этот вопрос 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 выполняет строгую оценку? (Да?)