идиоматические ленивые атомы в clojure

Я немного играю с атомами в clojure. У меня atom указывает на lazy-seq. В другом фрагменте кода я хочу обновить значение атома до результата выполнения next в последовательности, но, учитывая, что и swap!, и reset! возвращают выполнение обновленного значения, никогда не заканчивается. Я понял, что всегда могу обернуть вызов swap!, reset! в оператор do, а затем вернуть nil, но мне интересно, насколько это идиоматично или есть ли альтернативное решение для этого.

Не прекращается:

(def x (atom (range)))
(swap! x next)

Завершает

(def x (atom (range)))
(do (swap! x next) nil)
(first @x) ;1
(do (swap! x next) nil)
(first @x) ;2

person emanjavacas    schedule 27.04.2015    source источник


Ответы (2)


Проблема здесь не столько в Clojure, сколько в реплике, которую вы используете. Вызов swap! работает нормально, дело в том, что repl пытается распечатать результат, но не может, так как последовательность никогда не заканчивается. Вы можете установить количество элементов, напечатанных встроенным repl Clojure через (set! *print-length* 10). Но это не всегда будет работать, если у вас есть другое промежуточное ПО REPL, выполняющее другую логику печати.

На тему «как это сделать идиоматично» я бы дал вам два варианта:

  1. Оберните вызов swap! функцией, которая возвращает что-то другое.
  2. Или, в приведенном выше примере использования, поместите целое число в атом, а затем используйте (swap! x inc), чтобы получить следующее целое число.
person Timothy Baldridge    schedule 27.04.2015
comment
Спасибо! это дает решение моей проблемы. Я предполагаю, что перенос вызова в оператор do должен считаться идиоматичным в соответствии с вашим первым вариантом. - person emanjavacas; 28.04.2015

Ну можно было просто совместить своп! и первое:

(def x (atom (range)))
(first (swap! x next))
(first (swap! x next))

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

(def x (atom 0))
(swap! x inc)
(swap! x inc)
person Alex Miller    schedule 27.04.2015
comment
спасибо за ваш ответ, на самом деле это упрощенная версия моего кода. На самом деле у меня не просто диапазон, а другой вид ленивой последовательности, в которой не всегда следующее значение равно предыдущему значению плюс один. - person emanjavacas; 27.04.2015