Можно ли создавать круговые ссылки в Clojure?
Игнорируя собственные взаимодействия и переходные процессы, можно ли создавать любые структуры данных в Clojure, содержащие прямые циклические ссылки?
Казалось бы, неизменяемые структуры данных могут содержать только ссылки на предыдущие версии. Существуют ли какие-либо API-интерфейсы Clojure, которые могут создать новую структуру данных, которая имеет ссылку на себя?
В схеме есть форма letrec, которая позволяет создавать взаимно рекурсивные структуры, но, насколько я могу судить, Clojure не имеет ничего подобного.
Этот вопрос связан с переносом Clojure в iOS - который не содержит сборку мусора, но имеет подсчет ссылок.
Ответы
Ответ 1
Вы можете создать круговую ссылку очень легко, поставив некоторую форму ссылки внутри структуры данных, а затем обновив ссылку, чтобы вернуться к общей структуре.
Тривиальный пример:
(def a [(atom nil)])
(reset! (first a) a)
Это создаст список с одним элементом, который является атомом, который указывает на список.
Ответ 2
В Clojure большинство круговых структур данных будут явно проходить через какой-либо тип ref (например, атом).
Однако вы можете создать круговую последовательность (это несколько оксюморон):
(let [a (atom nil)] (reset! a (lazy-seq (cons 1 @a))))
И так как Clojure 1.2 с помощью deftype вы можете создавать другие типы данных, которые могут вводить округлость, не используя явно (по крайней мере, от кода пользователя) какой-либо тип ref.