задержка и отсрочка дают одинаковые результаты - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь понять разницу между delay и defonce, и одно должно использоваться поверх другого.

Ниже приведен фрагмент из tomekw/hikari-cp

(defonce datasource
  (delay (hcp/make-datasource datasource-options)))

Почему используются defonce и delay? Разве недостаточно просто использовать defonce?

Как я понимаю, оба позволят выполнить форму только один раз. В чем разница между ними?

1 Ответ

3 голосов
/ 08 октября 2019

в понятиях времени, когда тело оценивается, оба они вызывают тело ровно один раз, но эта форма касается не только времени выполнения, но и лени / рвения. Макрос delay оборачивает тело в специальный ссылочный объект и откладывает его выполнение до первой разыменования:

user> (let [x (delay 100)]
        (println x)
        (Thread/sleep 100)
        (println "woke up")
        (println x)
        (println @x)
        (println x)
        @x)

;;=> #delay[{:status :pending, :val nil} 0x273336d4]
;;   woke up
;;   #delay[{:status :pending, :val nil} 0x273336d4]
;;   100
;;   #delay[{:status :ready, :val 100} 0x273336d4]
;;   100

defonce само по себе стремится, возвращая отложенный блок сразу, но неего выполнение.

, что означает, что datasource устанавливается в инкапсулированный ленивый блок, который должен выполняться именно тогда, когда коду сначала нужно получить источник данных (вызывая deref или @),и defonce здесь, чтобы запретить переопределение этого вар. Я бы назвал это «ленивый синглтон».

user> (defonce value
        (do (println "DEFINING!")
            (delay
              (println "EVALUATING!")
              101)))
;;=> DEFINING!
#'user/value

user> value
#<Delay@b1388c1a: :not-delivered>

user> @value
;;=> EVALUATING!
101

user> value
#<Delay@1ed9ec81: 101>

;; `delay` caches value (doesn't print again)
user> @value
101
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...