определение взаимозависимых переменных - PullRequest
3 голосов
/ 17 февраля 2012

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

(declare a b)
(def a [1 b])
(def b [a 2])

Но после загрузки этого кода я получаю это:

test=> (first a)
1
test=> (second a)
#<Unbound Unbound: #'test/b>
test=> (first b)
[1 #<Unbound Unbound: #'test/b>]
test=> (second b)
2

ясно, это не так, как это должно работать. Я понимаю, что печать такой структуры приведет к переполнению стека, но мне не нужно печатать ее. Как мне это сделать?

Ответы [ 3 ]

3 голосов
/ 17 февраля 2012

Вы можете сделать следующее:

(declare a b)
(def a [1 #'b])
(def b [#'a 2])

@(a 1)
=> [#'user/a 2]

Обратите внимание, что #' - это макрос для чтения для ссылки на переменную.

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

EDIT

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

(def my-model
  {:a 
      {:name "Entity A" 
       :references [:b]}
   :b 
      {:name "Entity B"
       :references [:a]}}
1 голос
/ 17 февраля 2012

Во-первых, это очень похоже на проблему XY.

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

user=> (set! *print-level* 2)  ; this is necessary to stop the infinite print recursion
2
user=> (def a (atom [1]))
#'user/a
user=> (def b (atom [a 2]))
#'user/b
user=> (swap! a conj b)
[1 #<Atom@19ed00d1: #>]
user=> @a
[1 #<Atom@19ed00d1: #>]
user=> @b
[#<Atom@5c6c2308: #> 2]
0 голосов
/ 21 февраля 2012

Ленивая оценка может помочь:

user=> (declare a b)
#'user/b
user=> (def a [1 (lazy-seq b)])
#'user/a
user=> (def b [(lazy-seq a) 2])
#'user/b
user=> (first a)
1
user=> (second b)
2
user=> (second a) ;stack overflow
user=> (first b) ;stack overflow
user=> (take 42 (second a)) ;still overflow as it's infinitely deep
user=> (take 42 (first b)) ;still overflow as it's infinitely deep

Надеюсь, это поможет, хотя я не понимаю, как это будет полезно.

...