2010-09-12 2 views
22

Игнорирование встроенного взаимодействия и переходных процессов, возможно ли создавать любые структуры данных в Clojure, содержащие прямые циклические ссылки?Можно ли создавать круговые ссылки в Clojure?

Казалось бы, неизменные структуры данных могут содержать только ссылки на предыдущие версии самих себя. Существуют ли API-интерфейсы Clojure, которые могут создать новую структуру данных, которая имеет ссылку на себя?

Схема имеет форму letrec, которая позволяет создавать взаимно рекурсивные структуры, но, насколько я могу судить, у Clojure нет ничего подобного.

Этот вопрос связан с переносом Clojure на iOS - который не содержит сбор мусора, но имеет счет ссылок.

+0

Вот так тесно связанный вопрос SO: [Как создать ленивую секвенцию, анонимную рекурсивную функцию в Clojure?] (Http://stackoverflow.com/questions/3373157/how-to-create-a-lazy- сл генерирующим-анонимную-рекурсивной-функции-в-Clojure). См. Мой ответ на него для ряда возможных подходов. Один из них - с помощью макроса 'letrec' какого-то типа - см. [Этот Gist] (http://gist.github.com/486880) для моей версии (которая работает как' letrec' Scheme). –

+0

Спасибо за все ответы. Похоже, мне понадобится полный GC для обработки Clojure, и я экспериментирую с Gambit Scheme в качестве цели перевода. –

+0

Возможно, вас это интересует [предложение обмена в стеке] (http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2 «обзор кода»). Он почти готов начать бета-тестирование, просто нужно еще несколько. – greatwolf

ответ

14

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

Тривиальный пример:

(def a [(atom nil)]) 

(reset! (first a) a) 

Это позволит создать список с одним элементом, который является атом, который указывает обратно на список.

+0

Спасибо за ответ. Я бы использовал только тип ref как объект верхнего уровня, поэтому я никогда не рассматривал это. –

+0

- это var, который указывает на список, который указывает на атом, который ссылается на var –

+1

@Arther - технически это var, который указывает на вектор, содержащий атом, который указывает на вектор. т. е. сам var не находится в круговом цикле. – mikera

8

В Clojure большинство круговых структур данных будут явно проходить через какой-либо тип ref (например, атом).

Однако вы можете создать круговую последовательность (это несколько оксюморон):

(let [a (atom nil)] (reset! a (lazy-seq (cons 1 @a)))) 

И так Clojure 1.2 с deftype вы можете создать другие типы данных, которые могут ввести округлость без использования явно (с USERCODE по крайней мере) любой тип ref.

Смежные вопросы