Forum: Public ReviewIssue: READ-SUPPRESS-CONFUSING
References: Margolin's PR comment #2 (X3J13/92-1402)
Margolin's PR comment #18 (X3J13/92-1418)
Flanagan's PR comment #7 (X3J13/92-1907)
Philpot's PR comment #1 (X3J13/92-2901)
Barrett's PR comment #9 (X3J13/92-3109), part 2
*READ-SUPPRESS* (X3J13/92-102 pp.23-21..22)
Sharpsign P (X3J13/92-102 sec.2.4.8.14)
Sharpsign C (X3J13/92-102 sec.2.4.8.11)
Category: CHANGE
Edit history: 5 Jan 1993, Version 1 by Margolin
22 May 1993, Version 2 by Loosemore (delete bogus reference
to ":" and "@" in dispatching macro syntax)
Status: Proposal GENERALIZE passed 9-2 on letter ballot 93-302
Problem description:
The description of *READ-SUPPRESS* is confusing and incomplete. By
specifying the behavior of particular read syntaxes rather than a simple,
general strategy, some syntaxes (#C, #P, and#') have unintentionally been
omitted. And the wording of the description of the behavior of #(...) is
unclear as to whether the vector syntax is parsed and ignored or a vector
is actually constructed (there's a subtle difference between the CLtL and
dpANS wording, due to the lack of a pair of parentheses in the dpANS).
A strict reading of the current description of *READ-SUPPRESS* implies
that the reader must still construct objects in response to these
syntaxes (as well as user-defined reader macros that don't check the
variable). This is pretty wasteful considering that *READ-SUPPRESS*
exists primarily to support #+ and #-, which discard what they read with
*READ-SUPPRESS* true anyway.
In the case of #P, the lack of specification of its *READ-SUPPRESS*
behavior is a real annoyance, because some implementations have extended
it to allow non-strings to follow it. Users expect to be able to hide
such extensions using #+, but this isn't valid.
Proposal (READ-SUPPRESS-CONFUSING:GENERALIZE):
1) Replace the portion of the Description of *READ-SUPPRESS* from
"Extended tokens" through the entry for "#A, #S, #:" with:
When *READ-SUPPRESS* is true, READ, READ-PRESERVING-WHITESPACE,
READ-DELIMITED-LIST, and READ-FROM-STRING all return a first value of
NIL when they complete successfully; however, they continue to parse
the representation of an object in the normal way, in order to skip
over the object, and continue to indicate end-of-file in the normal
way. Except as noted below, any standard macro character (including
dispatching macro sub-characters) that is defined to read a following
object or token will do so, but not signal an error if the object
read is not of an appropriate type or syntax. Standard syntaxes and
macro characters will not construct any new objects (e.g. when
reading the representation of a symbol, no symbol will be constructed
or interned).
Dispatching macro characters (including #)
Dispatching macro characters continue to parse an infix numerical
argument, and invoke the
dispatch function. The standard # dispatching macro characters
do not enforce any constraints on the value or existence of the
numerical argument.
2) Create a Notes section that recommends that user-defined and
implementation-defined macro characters behave analogously to the
standard macro character, i.e. when *READ-SUPPRESS* is true they should
ignore type errors when reading a following object and dispatching macro
characters should allow NIL as an infix parameter.
3) Change the specifications of #C and #P to specify that they are
followed by the representation of an object. Then specify how they are
interpreted when those objects are a list of two real numbers (for #C) or
a string (for #P).
Examples:
(let ((*read-suppress* t))
(dolist (string '("#(foo bar baz)" "#P(:type :lisp)" "#c1.2" "foo"))
(progn (print (read-from-string string))
t))
could print
Test Cases:
(let ((*read-suppress* t))
'("#(foo bar baz)" "#P(:type :lisp)" "#c1.2")))
Rationale:
1) Specifies a general behavior for *READ-SUPPRESS* that is applicable to
all reader syntaxes that are described in terms of the representations of
objects.
2) Encourages implementors and users to extrapolate from this standard
behavior.
3) Specifies #P and #C in such a way that change 1 applies.
Current practice:
For the Example form, Genera 8.1 prints NIL, NIL, NIL (it seems to
implement the proposal); Lucid 4.1 and CMU CL 16d print NIL, ERROR, NIL;
WCL 2.1 prints #(NIL NIL NIL), ERROR, ERROR.
Cost to Implementors:
Should be minor.
Cost to Users:
When *READ-SUPPRESS* is bound via #+ or #-, the change should be upward
compatible, since any objects constructed by the reader will not be
visible. Direct users of *READ-SUPPRESS* may notice the difference, but
it seems unlikely that anyone is depending on any of the current
behaviors.
Cost of non-adoption:
Users will have to avoid using some implementation-dependent syntaxes in
#P macros.
Performance impact:
Minor.
Benefits:
More ability to include implementation-dependent syntax extensions in
portable source code.
Esthetics:
A general description of behavior is better than lots of specific cases.
Editorial Impact:
Minor. The changes are confined to the three sections mentioned above.
Discussion:
Barmar originally wanted to specify that standard dispatching macros
would parse the numerical argument but ignore it (always passing NIL to
the dispatch function). Flanagan convinced him to leave that part as it
was originally (the numeric argument is parsed but standard dispatch
functions don't enforce restrictions on it). It doesn't seem to be a big
deal either way.