On Wed, 15 Sep 2010 11:48:09 -0700
Michael Ossareh <ossa...@gmail.com> wrote:

> Hi Guys,
> 
> One of the things that has struck me about clojure, by virtue of being
> a lisp, is the concision of the code - I really find it very
> attractive. However yesterday I found something that I couldn't work
> out how to do in a concise manner. Clearly commenting the code was a
> priority once I got it working, however I'd like to ensure I'm doing
> this correctly.
> 
> Much of my functional experience comes from JS and dealing with the
> immutability of our data structures is a very interesting learning
> process.
> 
> I have a map (a sorted map) which maps an int to a map. The inner map
> contains a vector of data to which I want to conj elements into.
> 
> 
> { 0 {:title "some str"
>       :meetings [{ ... meeting data ... }
>                       { ... meeting data ... }
>                       { ... meeting data ...}]}
> 
>  1 {:title "some other str"
>       :meetings [{ ... meeting data ... }
>                       { ... meeting data ... }
>                       { ... meeting data ...}]}
> 
>  .....
> 
>  n {:title "some n str"
>       :meetings [{ ... meeting data ... }
>                       { ... meeting data ... }
>                       { ... meeting data ...}]}}
> 
> 
> In JS I'd have a loop which looks somewhat like this (assume the data
> above is called storedData and that newData has the data which I wish
> to insert into storedData);
> 
> newData.forEach(function(data) {
> 
>   var key = .... ;
> 
>   if (!storedData[key])
>     storedData[key] = {title: "title"}, meetings:[]}
> 
>   storedData[key].meetings.push(data) ;
> 
> })
> 
> In clj, I've ended up with something along the lines of the following
> (edited from what I have in my code base to match the JS example
> above):
> 
> (loop [data (sorted-map)
>          collection newData
>          meeting (first collection)]
> 
>   (def key ( .... ))

As a general rule, def should only be used at the top level. You
probably want (let [key ...] (if ...) here.

>   (if (not (nil? (next collection)

Minor nit: (not (nil? X)) is better spelled (seq? X))
And you seem to be missing a close paren or two here.

>     (recur (cond (not (nil? (data key)))
> 
>                        (assoc data key
>                           (assoc (data key)
>                             :meetings
>                             (conj ((data key) :meetings) meeting)))
> 
>                (true? true)
>                  (conj data [key {:title "some str" :meetings [meeting]}])))
> 
>    data))
> 
> 
> The middle section, with the assoc(es) and conj, just doesn't read as
> nicely as the rest of my clojure. Is this a symptom of my data
> structure or is there a more concise way to conj my data into these
> inner vectors?

That's actually a standard idiom, except you missed the assoc-in and
get-in functions:

(assoc-in data key :meetings (conj (get-in data key :meetings) meeting)

Should do what you want.

> Also, as a secondary concern, I read on here a while ago that when you
> find yourself typing "((" it's a sign of an issue - how, given the
> data structure I've to work with, woud you access the title of a value
> if not using that "((" syntax, i.e. ((data key) :title)?

I'm not sure where that came from, bug get-in and assoc-in solve that
as well.

       <mike
-- 
Mike Meyer <m...@mired.org>             http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

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