Re: Unreadable Objects: current status and where to go
Marc Nieper-WiÃkirchen 09 Dec 2022 18:33 UTC
Am Fr., 9. Dez. 2022 um 18:53 Uhr schrieb Lassi Kortela <xxxxxx@lassi.io>:
>
> > If you stick to #<...> (the original domain of SRFI 243), you can
> > really only make one effective constraint, namely the following:
> >
> > "A Scheme implementation supports SRFI 243 if its standard reader (and
> > its read/get-datum procedure(s)) signal an error/raise an exception
> > when the token #< is read."
> >
> > (Everything else is non-normative.) Given this specification, R6RS
> > systems would all support SRFI 243 and probably most R7RS systems as
> > well.
>
> It might make sense to specify a procedure,
>
> (write-unreadable-object object)
>
> that writes `object` using the customary notation of the Scheme
> implementation.
So OBJECT here is a Scheme datum value that must not be confused with
the unwritable object itself, right?
I am wondering what the actual meaning of the OBJECT as a Scheme would
be. For example, in Chez, (open-output-string) prints as #<output
port string>, which would probably become #?(output port string) in
your proposal. But interpreting the string "output port string" as a
list of three symbols is not meaningful, is it? Or should it be
#?"output port string"?
>
> For implementations using #? it would be as simple as:
>
> (define (write-unreadable-object object)
> (write-string "#?")
> (write object))
>
> For implementations using #< it could be something like:
>
> (define (write-unreadable-object object)
> (write-string "#<")
> (write (if (or (null? object)
> (pair? object))
> object
> (list object)))
> (write-string ">"))
>
> or:
>
> (define (write-unreadable-object object)
> (write-string "#<")
> (cond ((list? object)
> (for-each (lambda (item)
> (write-string " ")
> (write item))
> object))
> (else
> (write-string " ")
> (write object)))
> (write-string " >"))
>
> or whatever else preserves the closing ">" as unambiguous.
I guess that the native format of some (most?) implementations is just
#<STRING>, where STRING is an (informal) string of characters. So
does it really make sense to allow implementations to use their native
format when the closing ">" has to be unambiguously parsable?
>
> Given the chaotic situation in the field, it's probably not worthwhile
> to attempt to write any readers that skip #<...>, but the above solution
> can unify #<...> and #?datum from the Scheme programmer's (and Scheme
> _implementation_ programmer's) point of view, and paves the way for
> standardizing well-formed unreadable-object syntax in the future.
>
> > If you move to #?, the focus of SRFI 243 seems to change considerably.
> > Could you write down the intended normative part in a few sentences of
> > such a version of SRFI 243?
>
> Change the RnRS grammar so <compound datum> includes <unreadable>
>
> where <unreadable> == "#?" <datum>
You cannot change <compound datum> because this can be a <datum>, and
this is what the read procedure successfully parses (see 7.1.2 of the
R7RS).
> When `(read)` reads <unreadable>, it raises an error (we could specify a
> standard subtype of read-error for this purpose, call it e.g.
> unreadable-object-error).
If this is all that we want, then it will be enough to specify a new
token #? whose semantics is the reader must signal an error when it
reads it. Or do you want that #?(foo bar) signals an error, but
#?(foo . . baz) not necessarily?
> and export library procedure (write-unreadable-object object) which
> writes that syntax.
I should also mention an argument that speaks against inventing a new
#? syntax: The #-lexical syntax-namespace is small and precious, so
effectively doubling the syntax from #< to #< and #? for reader errors
may be a bit costly.