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