Отложенная оценка в Clojure

У меня возникли проблемы с пониманием того, как макрос delay работает в Clojure. Кажется, он не делает того, что ожидает от него (то есть: откладывает оценку). Как вы можете видеть в этом примере кода:

; returns the current time
(defn get-timestamp [] (System/currentTimeMillis))

; var should contain the current timestamp after calling "force"
(def current-time (delay (get-timestamp)))

Однако вызов current-time в REPL появляется, чтобы сразу оценить выражение, даже не используя макрос force:

user=> current-time
#<[email protected]: 1276376485859>
user=> (force current-time)
1276376485859

Почему оценка get-timestamp не была отложена до первого вызова force?

Ответы

Ответ 1

Печатное представление различных объектов, которое появляется в REPL, является произведением многомерного метода, называемого print-method. Он находится в файле core_print.clj в Clojure источниках, которые составляют часть того, что входит в пространство имен clojure.core.

Проблема в том, что для объектов, реализующих clojure.lang.IDeref - интерфейс Java для вещей deref/@ может работать on - print-method включает значение, стоящее за объектом в напечатанном представлении. Для этого ему нужно deref объект, и хотя специальные условия сделаны для печати неудачных агентов и ожидающих фьючерсов, задержки всегда принудительно.

На самом деле я склонен считать это ошибкой или, в лучшем случае, ситуацией, нуждающейся в улучшении. В качестве обходного пути сейчас проявляйте особую осторожность, чтобы не печатать невыдержанные задержки.