On Mon, Dec 6, 2010 at 2:57 AM, Benny Tsai <benny.t...@gmail.com> wrote:
> When I saw the part about traversing an arbitrarily nested collection,
> I immediately thought of clojure.walk (http://clojure.github.com/
> clojure/clojure.walk-api.html).  I ended up with this:
>
> (use 'clojure.walk)
>
> (defn all-vals [k coll]
>  (let [vals (atom [])
>        find-val (fn [form]
>                   (if-let [val (k form)] (swap! vals conj val))
>                   form)]
>    (prewalk find-val coll)
>   �...@vals))
>
> user=> (all-vals :distance {:goat "al" :distance 35})
> [35]
>
> user=> (all-vals :distance [{:goat "al" :distance 35}
>                     {:goat "paula" :distance 25}])
> [35 25]
>
> user=> (all-vals :distance [{:goat "al" :distance 35}
>                     {:goat "paula" :distance 25 :other {:distance 99}}])
> [35 25 99]
>
> I wanted to use walk in a purely functional manner (instead of the
> current approach of iteratively updating 'vals').  However, I was
> unable to do this, given that the function passed in to prewalk needs
> to preserve the structure of the nested collections.  Hopefully
> someone can find a way to use walk in a purely functional way here.

I dunno. Seems kind of pointless, when

(defn values-of [k coll]
 (if (instance? java.util.Map$Entry coll)
   (recur k [(key coll) (val coll)])
   (if-let [s (try (seq coll) (catch Exception _ nil))]
     (let [not-found (Object.)
           v (if (or (associative? coll) (instance? java.util.Map coll))
               (get coll k not-found) not-found)
           v (if-not (= v not-found) [v])
           vs (map #(values-of k %) s)]
       (apply concat v vs)))))

is only one line longer than what you have (counting the (use ...) and
following blank line), is pure functional, and uses only clojure.core.
And probably works on some of the java.util collections where the
clojure.walk version probably fails.

In fact, your code seems to require k to be a keyword, instead of
allowing it to be a string, or a number, or even nil.

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