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