Как лень Clojure взаимодействует с вызовами Java/нечистым кодом?
-
27-10-2019 - |
Вопрос
Мы наткнулись на вопрос в нашем коде сегодня и не смогли ответить на этот вопрос:
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 выполняет строгую оценку? (Да?)
Решение
Ленивые Seqs Clojure Chunk около 30 предметов, поэтому маленькая накладная головка еще больше уменьшается. Это не выбор пуриста, а практичный. Проконсультируйтесь с «радостью Clojure» для обычного решения, чтобы реализовать один элемент в момент времени.
Lazy SEQ не идеально подходит для нечистых функций по причине, с которой вы столкнулись.
Clojure также будет оцениваться строго, но с макросами вещи немного по -другому. Встроенные такие как if
Естественно проведет оценку.
Другие советы
Ленивые конструкции оцениваются более или менее, когда это удобно для реализации, независимо от того, что в них упоминалось. Так что, да, программист должен быть осторожным и принудительно реализовать ленивые SEQ, когда это необходимо.
Я понятия не имею, что вы имеете в виду под строгой оценкой.