Re: let accepting a vector
On Nov 13, 8:36 am, Stuart Halloway <[EMAIL PROTECTED]> wrote: > Hi Meikel, > > I spent a few minutes trying to write a macro to do this that doesn't > use eval. So far no good. Is it truly impossible, though? I have never > seen a good discussion of "things that can be done only with eval". > Any pointers? > The admonitions against eval are important, because people frequently get confused about macros, compile time, runtime etc. 99.9% of the time, especially when you are starting out, you shouldn't be using eval. The purpose of a macro is to transform a form into another form on behalf of the compiler. That's all! The fact that CL and Clojure macros can run arbitrary code makes them powerful, but doesn't change that fundamental purpose. People see them and think - oh, this is just a function that doesn't evaluate its arguments, and start writing macros for their runtime values, or worse yet, their effects. That's wrong! People often think they need runtime code generation without thinking it all the way through - if you write something that generates code at runtime, especially new names, how can the other code that you wrote prior to runtime use it? Macros allow you to do dynamic code generation that is accessible to other code prior to runtime. Is there ever a reason to generate code at runtime? Sure - to write a repl, or an interpreter. Of course, I've overstated everything, but it's only because, until you've developed an understanding of the above, you shouldn't be trying anything trickier. That said, and I'm loath to show this, the original example begs the conflation of compile and runtime. Here's how to do it without eval: ; gross - please don't write code like this!!! (def bindings-list '[one 1]) (defmacro list-let "a horrible macro that expects to be passed the name of a global var that contains a binding list" [bs & body] (let [blist (var-get (resolve bs))] `(let ~blist [EMAIL PROTECTED]))) (macroexpand-1 '(list-let bindings-list one)) -> (clojure.core/let [one 1] one) (list-let bindings-list one) -> 1 list-let is passed the name of a var that it needs to resolve at compile time. It does so, gets its value, then inserts that form into its expansion. The problem is, people may write things like this and expect the expansion to use the runtime value of bs at each expansion point - not so. The purpose of a macro is to transform a form into another form on behalf of the compiler. That's all! Rich --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: let accepting a vector
Hi Stuart, > I spent a few minutes trying to write a macro to do this that doesn't > use eval. So far no good. Is it truly impossible, though? I have never > seen a good discussion of "things that can be done only with eval". > Any pointers? The problem is, that macros happen at compile time, while a Var holds a value at runtime. So when we write a macro à la (defmacro my-let [bvec & body] `(let ~bvec [EMAIL PROTECTED])) And call it as (my-let some-vec ...), then the macro does not see the value of Var named some-vec, but the symbol some-vec itself. Hence, you need eval: you inject the value of some-vec and *compile* the expression at *runtime*. (Maybe this is the definition of when eval is needed...) Hope, this makes sense. Sincerely Meikel --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: let accepting a vector
Hi Meikel, I spent a few minutes trying to write a macro to do this that doesn't use eval. So far no good. Is it truly impossible, though? I have never seen a good discussion of "things that can be done only with eval". Any pointers? Cheers, Stuart > Hi, > > On 13 Nov., 07:27, Larrytheliquid <[EMAIL PROTECTED]> wrote: >> Is there a way to pass a vector to a function like let, rather than >> manually >> typing in the brackets? > > let is not a function, but a special form (see: > http://clojure.org/special_forms) > . > It is only possible via eval to achieve the desired effect. > > (def *bvec* '[x 1 y 2]) > > (eval > `(let ~*bvec* > (+ ~'x ~'y))) > > And this is almost surely not what you want to do. eval is a strong > code > smell, if not stench. > > Sincerely > Meikel > > > > --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: let accepting a vector
Hi, On 13 Nov., 07:27, Larrytheliquid <[EMAIL PROTECTED]> wrote: > Is there a way to pass a vector to a function like let, rather than manually > typing in the brackets? let is not a function, but a special form (see: http://clojure.org/special_forms). It is only possible via eval to achieve the desired effect. (def *bvec* '[x 1 y 2]) (eval `(let ~*bvec* (+ ~'x ~'y))) And this is almost surely not what you want to do. eval is a strong code smell, if not stench. Sincerely Meikel --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
let accepting a vector
Is there a way to pass a vector to a function like let, rather than manually typing in the brackets? ;;; normal let (let [one 1] one) ;;; list let (def bindings-list '[one 1]) (list-let bindings-list one) -- Respectfully, Larry Diehl www.larrytheliquid.com --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---