#

## Issue READ-SUPPRESS-CONFUSING Writeup

    Forum:		Public Review
    Issue:		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"))
          (unless
            (ignore-errors
              (progn (print (read-from-string string))
                     t))
            (print 'error))))
      could print
      #(NIL NIL NIL)
      ERROR
      ERROR

    Test Cases:

      (let ((*read-suppress* t))
        (mapcar #'read-from-string
                '("#(foo bar baz)" "#P(:type :lisp)" "#c1.2")))
      -> (NIL NIL NIL)

    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.

Copyright 1996-2005, LispWorks Ltd. All rights reserved.