<div dir="ltr">A couple points:<div><br></div><div>First, I disagree with this detail in Thomas' analysis, and can't quite understand what it claims.</div><div><br></div><div><span style="font-size:12.8000001907349px">   the implementation is free to act as though the method you defined is in fact defined, but completely ignore it when doing dispatch.</span><br></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">Unclear to what this "doing dispatch".  print-object is presumably a standard-generic-function, and it is called in normal printing, and how CLOS handles that call is well defined.  If user code has defined a print-object method for a user-code-defined standard-class or structure-class, print-object _must_ invoke that method in the usual way.  And if that method calls call-next-method, it could well be the case that some implementation-provided method receives control, possibly even a method specialized on class t.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">There can be no bypassing of normal CLOS operation for print-object.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">What the prohibition on defining methods on system classes means is that user code cannot affect how non-pretty printing handles classes defined in the ANS, which is a larger set than built-in classes.  User code also cannot (defmethod print-object ((x standard-object) stm) ...) even though standard-object is not a built-in class.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">Unfortunately, the prohibition in the ANS is not quite watertight.  The prohibition is oddly based on symbols that name classes and which are exported from the CL package.  One could imagine an additional built-in implementation class interposed into the class lattice (perhaps a sub/supertype of character or vector) named by a non-exported symbol.  The ANS prohibition technically allows user code to (re)define a print-object method on that symbol, although this clearly violates the spirit and intention of the prohibition.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">It makes sense to prohibit changes to how built-in classes are printed, sine in rare cases operation of other modules may depend on printed representation.  Suppose #'car works by making a TCP connection to a relational database server that stores the car and cdr of each cons.  To make that connection the implementation must be able to depend on the standard printing functions behaving normally.  Changes to the several printer special vars can be masked using with-standard-io-syntax, and the current pprint-dispatch table can be lambda bound, but there is no simple or efficient way to shadow print-object methods.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">Finally, here is what everyone has been missing about this matter.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">A conforming implementation must include CLOS, and must non-pretty write using print-object.  But a conforming implementation could include just a single print-object method:</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">(defmethod print-object (x stm) (write x :stream stm))  ; write presumably contains a big typecase</span></div><div><span style="font-size:12.8000001907349px"><br></span></div><div><span style="font-size:12.8000001907349px">X3J13 considered CLOS to be important.  But existing CLtL1 implementations already had working printers that handled all CLtL1 objects and which obviously did not use CLOS method dispatch.  Only minor changes would be necessary to accommodate printing of standard-objects, but to gain acceptance new features were often couched in definitions that imposed the least-possible impact on existing implementations.  That's why the requirements for print-object of implementation classes is so loose.</span></div><div><span style="font-size:12.8000001907349px"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Aug 29, 2015 at 7:20 AM, Edi Weitz <span dir="ltr"><<a href="mailto:edi@weitz.de" target="_blank">edi@weitz.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thomas,<br>
<br>
That was the piece of the puzzle I had missed.<br>
<br>
Thanks,<br>
Edi.<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
On Sat, Aug 29, 2015 at 12:04 PM, Thomas Burdick <<a href="mailto:thomas@burdick.fr">thomas@burdick.fr</a>> wrote:<br>
> Hi Edi,<br>
><br>
> That certainly reads to me as though the intent is for print-object to be<br>
> the decision point (at least in cases where *print-pretty* is false).<br>
><br>
> However, as far as I understand 11.1.2.1.2:<br>
><br>
> Except where explicitly allowed, the consequences are undefined if any of<br>
> the following actions are performed on an external symbol of the COMMON-LISP<br>
> package:<br>
><br>
> [...]<br>
><br>
> 19. Defining a method for a standardized generic function which is<br>
> applicable when all of the arguments are direct instances of standardized<br>
> classes.<br>
><br>
><br>
> I think the much-feared "consequences are undefined" phrasing there means<br>
> the implementation is free to act as though the method you defined is in<br>
> fact defined, but completely ignore it when doing dispatch. (or reformat<br>
> your hdd or make monkeys fly or whatever).<br>
><br>
> -Thomas<br>
><br>
>> From: <a href="mailto:edi@weitz.de">edi@weitz.de</a><br>
>> Date: Sat, 29 Aug 2015 11:10:15 +0200<br>
>> To: <a href="mailto:pro@common-lisp.net">pro@common-lisp.net</a><br>
>> Subject: PRINT-OBJECT for built-in classes<br>
><br>
>><br>
>> The following "works" in three different CL implementations I tried<br>
>> while in three others the way complex numbers are printed doesn't<br>
>> change.<br>
>><br>
>> ? (defmethod print-object ((obj complex) stream)<br>
>> (format stream "#< ~A + ~A * I >"<br>
>> (realpart obj) (imagpart obj)))<br>
>> #<STANDARD-METHOD PRINT-OBJECT (COMPLEX T)><br>
>> ? #c(1 1)<br>
>> #< 1 + 1 * I ><br>
>><br>
>> My understanding of 22.1.2 of the standard is that each Lisp MUST have<br>
>> a PRINT-OBJECT method for complex numbers. The question then is<br>
>> whether I'm allowed to redefine it like above (I think I am) and/or<br>
>> whether an implementation is allowed to accept this redefinition<br>
>> without a warning but then to ignore it (which, as I said, is what<br>
>> happens in three respectable Lisps).<br>
>><br>
>> Thanks,<br>
>> Edi.<br>
>><br>
>> [Note: There's no point in talking me out of this as I don't actually<br>
>> want to do it anyway. It's just an example and I'm only interested in<br>
>> what exactly is governed by the standard. Complex numbers are also<br>
>> just an example. I'm interested in PRINT-OBJECT for built-in classes<br>
>> in general.]<br>
>><br>
<br>
</div></div></blockquote></div><br></div>