Thank you very much for this detailed explanation!

Michiel de Mare

On Dec 3, 2:47 pm, Rich Hickey <[EMAIL PROTECTED]> wrote:
> 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