Frank C.
Frank C.

Reputation: 8088

How to dereference a dynamically interned atom?

I am registering a symbol dynamically and I can verify it is successful:

(defn- register[x]
  (intern 'foo.core x (atom {})) 
  (println "Var " x " gets " (var-get (get (ns-interns 'foo.core) x))))

; Var  Persons  gets  #object[clojure.lang.Atom 0x688a2c09 {:status :ready, :val {}}]

My core question is: how to use x in (swap!...

Second question is: how to dereference x to get the map itself?

Final question is: Is there a cleaner approach?

Upvotes: 0

Views: 172

Answers (1)

leetwinski
leetwinski

Reputation: 17859

intern function returns a variable object, and since it is a reference value it can be dereferenced (with @ or deref). It can also be returned from the function and operated on, to get the desired result. The value this var points to (or the var's binding) points to an atom, and that is another reference value, and can also be dereferenced.

here's a little example of how to deal with this case:

user> (ns my.ns)
nil

my.ns> (in-ns 'user)
#namespace[user]

user> (defn register-trace [v-name]
        (let [v (intern 'my.ns v-name (atom {}))]
          (println (str "v is " v))
          (println (str "v's contents is " @v))
          (println (str "v's internal value is " @@v))
          v))
#'user/register-trace

user> (register-trace 'asd)
;;=> v is #'my.ns/asd
;;=> v's contents is clojure.lang.Atom@6a6ee04b
;;=> v's internal value is {}
#'my.ns/asd

user> (let [var-atom @(register-trace 'my-var)]
        (swap! var-atom assoc :x 101))
;;=> v is #'my.ns/my-var
;;=> v's contents is clojure.lang.Atom@2164d9ed
;;=> v's internal value is {}
{:x 101}

user> @my.ns/my-var
{:x 101}

user> (swap! my.ns/my-var update :x inc)
{:x 102}

user> @my.ns/my-var
{:x 102}

Upvotes: 4

Related Questions