On Dec 3, 6:58 am, Michiel de Mare <[EMAIL PROTECTED]> wrote:
> Indeed, (print-dup (new StringBuffer) (new java.io.StringWriter))
> throws the same exception.
> But (new StringBuffer) in the REPL prints the stringbuffer just fine.
>
> Why does the exception only get triggered in macros?
>
> And doesn't print-dup need a default for unknown classes?
>
> On Dec 3, 12:23 pm, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote:
>
> > Hi,
>
> > On 3 Dez., 12:04, Michiel de Mare <[EMAIL PROTECTED]> wrote:
>
> > > This has nothing to do with eval. The following fails too:
>
> > > (defmacro foo [] (new StringBuffer))
> > > (foo)
>
> > The results at the Repl are printed via pr-on and
> > obviously print-dup doesn't know how to print a
> > StringBuffer.
>
> > Sincerely
> > Meikel

The purpose of a macro is to transform a form into another form on
behalf of the compiler.

If you want a call to (foo), to become a call to create a new
StringBuilder, you need to return a piece of data that is a call to
new, i.e. a list:

i.e. you want to write this form:

(foo)

you want it to expand into this form, i.e. the list of the symbols
'new and 'StringBuilder:

(new StringBuilder)

And the way to do that is this:

(defmacro foo []
  `(new StringBuilder))

(macroexpand '(foo))
-> (new java.lang.StringBuilder)

But that's not what this does:

(defmacro foo []
  (new StringBuilder))

That turns the list (foo) into a StringBuilder object, and asks the
compiler to compile that StringBuilder object:

(macroexpand '(foo))
-> #<StringBuilder >

As it says at:

http://clojure.org/evaluation

"Any object other than those discussed above will evaluate to itself."

So what you are asking the compiler to do when asking it to compile a
literal object like that, is to put that object into the compiled
bytecode. It ends up that very few objects can be represented in
bytecode - basically the primitives and Strings. So a language that
allows for literal objects other than those (as does Clojure) needs to
find a way to put them into the bytecode and restore them later.
Clojure does this by representing them as Strings, specifically by
print-duping them and reading them later. Therefor the only objects
that can be literals in code are those that support print-dup.

This has nothing to do with printing objects at the repl - that does
not use print-dup, just print-method.

Unfortunately there is no universally valid default definition for
print-dup. (a default I tried, printing a call to the ctor with the
toString value, works often, but not always). And were the default to
print something that failed at read time, those failures occur during
class static initialization time, where you really want to avoid
errors.

print-dup supports the vast majority of things one would like to treat
as constants in code, with some notable pseudo-value classes like Date
still to come, but embedding a literal StringBuffer in code is most
certainly a mistake.

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
-~----------~----~----~----~------~----~------~--~---

Reply via email to