> I suspect using eval in field-read is a bad idea (preformance?) but I
> couldn't come up with a better way to do it. access-spec
> needs to be a vector as its something thats returned by
> another function in my use case (otherwise I could have
> used it with ->).
No need for eval here:
(defn field-read [st as]
(loop [st st as as]
(if (first as)
(recur (get st (first as))
(rest as))
st)))
Best,
Graham
It looks like this has come up on IRC a few weeks ago:
http://clojure-log.n01se.net/date/2008-07-15.html#09:22
I had forgotten that when I brought it up again today:
http://clojure-log.n01se.net/date/2008-08-27.html#10:00
It seems to me you're already pretty close to what Rich wants.
--Chouser
apply actually can do the conj'ing for you:
(apply mk-get my-fridge (item-path :mango) :quantity)
--Chouser
I'm sorry -- remind me not to post untested code after my bedtime.
You're right, that won't work. Apply does allow you to provide
non-seq arguments followed by the single seq at the end. This is what
I was thinking about:
user=> (apply + 1 2 3 [4 5 6])
21
But the apply expression I wrote above has a seq that you want to
expand early in the list, and non-seq at the end. As you already
discovered, that just throws an exception.
So let me start over -- you want a function that takes a mix of keys
and vectors of keys, right? You could of course wrap the ones Rich
provided for your own use cases. For example if you always have one
vector followed by one plain key, you could do:
user=> (defn mk-get-1 [m v k] (apply mk-get m (concat v [k])))
#'user/mk-get-1
user=> (mk-get-1 my-fridge (item-path :mango) :quantity)
10
Or if you want to allow any kind of mixed vectors, seqs, and plain keys:
user=> (defn mk-get-2 [m & a] (apply mk-get m (mapcat #(if (or
(vector? %) (seq? %)) % [%]) a)))
#'user/mk-get-2
user=> (mk-get-2 my-fridge (item-path :mango) :quantity)
10
user=> (mk-get-2 my-fridge :fruits [:mango :quantity])
10
user=> (mk-get-2 my-fridge :fruits (list :mango :quantity))
10
user=> (mk-get-2 my-fridge :fruits [:mango] :quantity)
10
Neither of these strike me as very general. I don't have my own use
cases (yet) for these functions, so I shouldn't speak too confidently,
but mk-get-1 seems like a pretty specific case (exactly one vector
followed by exactly one plain key). And since vectors are perfectly
valid map keys, it's possible to build nested maps that can't be
accessed using mk-get-2:
user=> (mk-get {[:a :b] :c} [:a :b])
:c
user=> (mk-get-2 {[:a :b] :c} [:a :b])
nil
--Chouser