Even if WRITE is the primitive that PRIN1 and PRINC are written in terms of, it still has to bind all the variables to the corresponding keyword parameters (for the benefit of things like PRINT-OBJECT methods that get invoked within it).
Actually, I'm not totally sure this is valid. The spec says that supplied keywords cause the corresponding variable to be bound, but if a keyword parameter isn't supplied, the corresponding variable has the same value as it did when WRITE was invoked. My code above meets that requirement, but it does so by dynamically binding the variable to its value.
The difference becomes apparent if a function invoked during the WRITE assigns one of these variables. With the binding in place, the variable is restored to its previous value when WRITE returns.
-- Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
* Barry Margolin <barmar-6BD03F.12411929042...@news.eternal-september.org> :
Wrote on Sun, 29 Apr 2012 12:41:19 -0400:
| (defun write (object &key | ((:stream *standard-output*) *standard-output*)
| ((:array *print-array*) *print-array*)
| ((:base *print-base*) *print-base*)
| ...)
| (if *print-escape*
| (prin1 object)
| (princ object)))
|
| Even if WRITE is the primitive that PRIN1 and PRINC are written in terms | of, it still has to bind all the variables to the corresponding keyword | parameters (for the benefit of things like PRINT-OBJECT methods that get | invoked within it).
|
| Actually, I'm not totally sure this is valid. The spec says that | supplied keywords cause the corresponding variable to be bound, but if a | keyword parameter isn't supplied, the corresponding variable has the | same value as it did when WRITE was invoked. My code above meets that | requirement, but it does so by dynamically binding the variable to its | value.
The spec's statement "the value of the corresponding printer control
variable is the same as it was at the time write was invoked.", would be
vacuous if it was not meant to imply that the specified printer
variables were going to rebound dynamically by WRITE, (even when not
named as a keyword parameter)
| The difference becomes apparent if a function invoked during the WRITE | assigns one of these variables. With the binding in place, the variable | is restored to its previous value when WRITE returns.
I cannot imagine unconditionally assigning a global printer variable in
the innards of the printer as being anything but a bug.
PRINT-OBJECT cautions that "In general, the printer and the print-object
methods should not rebind the print control variables as they operate
recursively through the structure, but this is
implementation-dependent."
[A better example than WRITE for the OP would be the stream argument to
the PPRINT-LOGICAL-BLOCK macro. I think LW has some compliance issues
with the pprint-* functions, most likely related to the issue you
brought up above.]
Madhu <enom...@meer.net> wrote:
> * Barry Margolin <barmar-6BD03F.12411929042...@news.eternal-september.org> :
> Wrote on Sun, 29 Apr 2012 12:41:19 -0400:
> | (defun write (object &key > | ((:stream *standard-output*) *standard-output*)
> | ((:array *print-array*) *print-array*)
> | ((:base *print-base*) *print-base*)
> | ...)
> | (if *print-escape*
> | (prin1 object)
> | (princ object)))
> |
> | Even if WRITE is the primitive that PRIN1 and PRINC are written in terms > | of, it still has to bind all the variables to the corresponding keyword > | parameters (for the benefit of things like PRINT-OBJECT methods that get > | invoked within it).
> |
> | Actually, I'm not totally sure this is valid. The spec says that > | supplied keywords cause the corresponding variable to be bound, but if a > | keyword parameter isn't supplied, the corresponding variable has the > | same value as it did when WRITE was invoked. My code above meets that > | requirement, but it does so by dynamically binding the variable to its > | value.
> The spec's statement "the value of the corresponding printer control
> variable is the same as it was at the time write was invoked.", would be
> vacuous if it was not meant to imply that the specified printer
> variables were going to rebound dynamically by WRITE, (even when not
> named as a keyword parameter)
I thought it could just be a reminder that WRITE must NOT set or bind them to default values. When I was writing the above sample code, I almost left out all the defaults -- that would have violated this part of the spec.
> | The difference becomes apparent if a function invoked during the WRITE > | assigns one of these variables. With the binding in place, the variable > | is restored to its previous value when WRITE returns.
> I cannot imagine unconditionally assigning a global printer variable in
> the innards of the printer as being anything but a bug.
> PRINT-OBJECT cautions that "In general, the printer and the print-object
> methods should not rebind the print control variables as they operate
> recursively through the structure, but this is
> implementation-dependent."
> [A better example than WRITE for the OP would be the stream argument to
> the PPRINT-LOGICAL-BLOCK macro. I think LW has some compliance issues
> with the pprint-* functions, most likely related to the issue you
> brought up above.]
If the CL designers weren't trying to maintain consistency with the way MACLISP and Zetalisp did this, what they might have done was throw out all these variables, and use an opaque object analogous to RANDOM-STATE to hold all the printer/reader parameters.
-- Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***