On Nov 23, 9:56 pm, James Reeves <[EMAIL PROTECTED]> wrote:
> On Nov 23, 11:58 pm, Justin Giancola <[EMAIL PROTECTED]>
> wrote:
>
> > Neat. I noticed that you're forcing the arg lists into vectors in both
> > make-maps and in stubfn. Since they're not being manipulated at all,
> > you could just as easily leave them as seqs and everything will still
> > work.
>
> The reduce is a good idea, but your method of quoting the hash doesn't
> evaluate the return value:
>
> user=> (stub [(f 1 2) (+ 1 2)] (f 1 2))
> (+ 1 2)
>
> Whilst with the original:
>
> user=> (stub [(f 1 2) (+ 1 2)] (f 1 2))
> 3

Oops--when I realized the arg list hash keys were being evaluated
during stub function creation I should have addressed that directly
instead of just quoting the entire hash!

> This was why I turned it into a vector. It seemed the easiest way of
> getting a hash that I didn't have to quote, but whose values would be
> correctly evaluated.

Using vectors will work since they're self-evaluating, but you can
also prevent the unwanted evaluation by wrapping them in quote forms
as the hash is being assembled:

(defmacro stub [stubs & body]
  (let [stub-maps
        (reduce (fn [acc [[f & args] res]]
                  (assoc-in acc [f `'~args] res))
                {}
                (partition 2 stubs))]
    `(binding
         [~@(mapcat (fn [[fname fhash]]
                      `(~fname (fn [& args#] (~fhash args#))))
                    stub-maps)]
       [EMAIL PROTECTED])))

This way when the stub functions are created you end up with list
literals for keys and correctly evaluated values.

However, quoting the arg lists this way necessitates that calls to the
stub functions have arg lists identical to those used to generate the
stubs.

i.e.
user=> (stub [(f 1 2) (+ 1 2)] (f 1 2))
3

but

user=> (stub [(f 1 (+ 1 1)) (+ 1 2)] (f 1 2))
nil

So, you need to evaluate all of the args independently when building
the list literals, possibly with:
(defmacro stub [stubs & body]
  (let [stub-maps
        (reduce (fn [acc [[f & args] res]]
                  (assoc-in acc [f `(list [EMAIL PROTECTED])] res))
                {}
                (partition 2 stubs))]
    `(binding
         [~@(mapcat (fn [[fname fhash]]
                      `(~fname (fn [& args#] (~fhash args#))))
                    stub-maps)]
       [EMAIL PROTECTED])))

I'm not sure this is quite as easy to follow, but I'd prefer to avoid
proxying all of the arg lists through vectors just because they're
self-evaluating.


Justin

--~--~---------~--~----~------------~-------~--~----~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to