On 14 Nov., 20:22, John Harrop <jharrop...@gmail.com> wrote:
> On Sat, Nov 14, 2009 at 2:11 PM, John Harrop <jharrop...@gmail.com> wrote:
> > On Sat, Nov 14, 2009 at 11:42 AM, André Thieme <
> > splendidl...@googlemail.com> wrote:
>
> >> 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?
>
> > I think the design in this sort of case needs changing.
>
> > Repeated structure references also pose a problem for storage and retrieval
> > (at least if not using a real DB) as Clojure's prn and read will turn shared
> > substructures into separate copies.

Well, I want to have a real in-ram db. Just not a relational one.
My in-ram data structures can express very well what I want to say.
I wrote a serialize and restore function that can print refs, even
circular
referential refs containing each other.


> > What's needed here is to make all person lookups go through one point, the
> > *persons* table, so the :friends key would store a vector not of person
> > struct references but simply of names.

Ok, so you would vote for having my own my-ref and my-deref functions,
which
references/dereferences my objects, using an ID under the hood.


> > When you start using a real DB this won't change; only the name of the
> > concept will, to a "key column". Name will be a key column in the *persons*
> > table and will be how you get at particular rows (persons) in the table.

I see your point, I just want to mention that we are maybe so trained
to use
relational db system that we see only them as a “real db” :-)


> Actually, often you have to go further. For example, in the example above,
> to accommodate name changes, the name field can't be the key field or you're
> back to having to update every reference. There's also the possibility of
> duplicate names for two different people; you don't want it to blow up (or
> worse, mix two peoples' private data and make it all visible to both) as
> soon as your Facebook clone's second John Smith signs up.
>
> In situations like these, a computer-generated id is typically used as an
> immutable key field:
>
> table person
>
> id            name             age        friends
> 000           Karl             20         [002]
> 001           Jeff             22         [002]
> 002           Tina             19         [000 001]

Okay, that makes sense. Basically the idea is having my own
ref and deref function, and then have a ref on a hashmap of a global
object container. Good, that would work and not change my programming
model, as the current one also requires the use of (deref ..) at
several
places.


> (I took the liberty of assuming you actually want friends to be a symmetric
> relation, so add-friend will friend each person to the other.

Yeah, that‘s fine. My example is just made up to illustrate the point.

Thanks for your idea, this seems to be the right way to do it.
So, now I need to look into how I can get @ to be extended to deref
(= run a function I specify) instances of the
(deftype my-ref ...) type.

-- 
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