On Tue, Jan 27, 2009 at 9:20 AM, Daniel Jomphe <danieljom...@gmail.com> wrote:
>
> Michael Wood wrote:
>
>> I've seen various code snippets where people use something# in
>> functions.  Is there any point to this or gensym except in a macro?

The suffix# isn't made useful by being in a macro, but by being in a
syntax-quote.

user=> `foo#
foo__211__auto__

Note that the # was expanded into a unique symbol suffix.  However
using a # outside of a syntax-quote, such as in a regular function
doing a regular 'let', doesn't really buy you anything:

user=> 'foo#
foo#

> If anyone could chime in and tell me if macros are the only out of
> this problem, that would be really great. To simplify the problem to
> its essence, let's say I'd like, without using macros, the following
> to print better:
>
>  (print (first [= 1 2]))
> #<core$_EQ___2886 clojure.core$_eq___2...@830122>
>
> Hey, I just found out the following works:
>
>  (print (first '(=)))
> =

The difference is in the quoting.  Within [] each symbol is evaluated.
If = were at the head of a list, the whole list would be evaluated as
a function call:

user=> [1 (= 2 3) 4]
[1 false 4]

But since = is *not* appearing at the head of a list, Clojure sees
that it's the name of a Var and evaluates it as the object currently
stored in that Var.  Specifically the equality function.  And
functions print ugly:

user=> =
#<core$_EQ___3139 clojure.core$_eq___3...@1722456>

Moreover, there's very little useful information that you can
currently get out of a function object.  There's not even any metadata
or simple name.  About all you can get is the string you see above.

So the problem is that by allowing the = to be evaluated, you've lost
some information that in this case you still want.  This is analogous
to what would happen if you want to assert on a more complex form,
like (+ 1 2):

user=> (+ 1 2)
3

By the time it's evaluated, all you have is the Integer 3; you've lost
the information about the form that produced it.

This is exactly the benefit of quoting.  It allows you to pass an
unevaluated form to a function:

user=> '(+ 1 2)
(+ 1 2)

user=> '=
=

Of course now you have the opposite problem -- you've got the form,
but now you would still like to be able to evaluate it.  You might
choose to use 'eval' directly:

user=> (defn form-and-val [x] {:form x :val (eval x)})
user=> (form-and-val '(+ 1 2))
{:form (+ 1 2), :val 3}

...but eval is not recommended unless really necessary.  Also note
that as already described, I had to quote the arg.

And it's not necessary here, because this macros solve two problems at
once.  First, the value they return is code that will be compiled at
the same time as the rest of the code that uses your macro, so no
extra eval or compile step is needed.  Second, the values passed to a
macro act as if they'd already been quoted, so users of your macro
don't need to quote them explicitly.

user=> (defmacro form-and-val [x] `{:form '~x :val ~x})
user=> (form-and-val (+ 1 2))
{:form (+ 1 2), :val 3}

No quote, no eval.  Trying to avoid writing macros as much as possible
is a great rule of thumb.  But in this case I think it's justified.

--Chouser

--~--~---------~--~----~------------~-------~--~----~
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 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to