I watched http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey
and it is a very nice video. Rich mentioned around minute 9 to 10:05 a
big problem:
when some code gets handed data, can it be sure this thing is
immutable?

Clojure wants to help, because it encapsulates state in refs, which we
can deref.
When we deref something it feels like an immutable copy which will
never be
touched.

But in real programs things are not so easy. We have refs in refs.
To illustrate this I want to make up a simple example. Let‘s say we
have a web
application where people can register, and become friends with each
other.

To represent a person we want to have a (defstruct
person :name :age :friends)
(this could also be a deftype of course).
We want to store all persons on our website in a map. Their name will
be the
key. As more and more people register we need to update our map, so it
must
be a ref (or atom):
(def *persons* (ref {}))

Each person can also be changed, for example when he/she gets older,
or when
she found new friends.
Initially when someone registers he/she has no friends yet. To add a
user we
want something like:
(defn make-person [name age]
  (let [p (ref (struct person name age []))]
    (dosync
      (alter *persons* assoc name p))
    p))

Now three people register, and we have:
(make-person "Karl" 20)
(make-person "Jeff" 22)
(make-person "Tina" 19)

Dereferencing *persons* will result in:
{"Tina" #<r...@7ae6d: {:name "Tina", :age 19, :friends []}>,
 "Jeff" #<r...@125d92c: {:name "Jeff", :age 22, :friends []}>,
 "Karl" #<r...@14fa0ef: {:name "Karl", :age 20, :friends []}>}
Great so far.

People can become friends, so we need
(defn add-friend [#^String person #^String friend]
  (dosync
    (let [p (get @*persons* person)
           f (get @*persons* friend)]
    (alter p update-in [:friends] conj f))))

So, Tina can get the friends Karl and Jeff:
(add-friend "Tina" "Karl")
(add-friend "Tina" "Jeff")

Now the problem is: *persons* acts as our data base, and
when a request comes in (to our web application, hosted by,
say, Compojure) we want to see a consistent snapshot of the
DB.
But derefing *persons* won't do this for us.
Even when we deref Tina, we can not be sure who her friends
are, as those live in their own refs.
They have to. If Karl gets one year older then we only want to
change his date, and not traverse all persons first and see if
they have Karl as a friend and if yes updating his age there too.

How can we handle this situation?
Is it possible to implement a function “deep-deref” which works
as blindingly fast as deref does?
I find this very important, and this is of great practical relevance
for me. Please share your ideas.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to