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