Re: let accepting a vector

2008-11-13 Thread Rich Hickey



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

2008-11-13 Thread mb

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

2008-11-13 Thread Stuart Halloway

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

2008-11-13 Thread mb

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

2008-11-13 Thread Larrytheliquid
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
-~--~~~~--~~--~--~---