Am Fr., 20. März 2020 um 19:21 Uhr schrieb John Cowan <>:

On Fri, Mar 20, 2020 at 12:52 AM Shiro Kawai <> wrote:

The problem is that what port-position returns is *not* what get-position returns.  The port can buffer multiple characters, and the user-supplied get-position can't know how many characters has been read from the port.  It can returns the position where next read! will read from.   The port internally offsets the position, taking into account of what's remaining in its buffer. 

R6RS has nothing to say about character buffering as opposed to byte buffering, and seems to have been written as if it doesn't exist.
Thus what get-position returns must be in sync of what the implementation's port expects.

Without character buffering this should automatically be correct.  I also think that implementations should not even byte-buffer custom ports, though probably some do.

On Fri, Mar 20, 2020 at 3:29 AM Marc Nieper-Wißkirchen <> wrote:

The problem occurred to me when I wrote my syntax expander for R7RS.  First, I couldn't use R7RS's `read' procedure to implement `include-ci' because there is no way to portably tell the builtin reader to read, say, `#\Space' as `#\space'.  Thus, I had to write my own `read' procedure.

Okay, I see why that's necessary.  It is irritating; it would be better if there were a resumable exception that lets a caller define what #\iota means rather than relying on the implementation.  It also means, for example, that if a system supports both #\Alpha and #\alpha (in the way that HTML defines both &Alpha; and &alpha;), the distinction is lost when reading case-folded.  Presumably legacy code would not make use of such escapes, however.

The distinction between the symbols `foo' and `FOO' is also lost in legacy code.

This, however, would need to attach some state to the supplied port to become a full replacement for the builtin `read':

I talked to the Chicken people about this, and they don't see any reason why case-folding has to be port-specific.  In Chicken case-folding is  a parameter that is globally visible, but only `read` normally makes use of.  While this approach is not as theoretically neat, I think that the situation of reading S-expressions concurrently from two sources that don't agree on case-folding is vanishingly rare in practice. Certainly it is not needed to support include-ci, as reading from the included port is strictly nested.

With that approach, they cannot implement R7RS fully.

Apart from this, having a global parameter looks like a very wrong abstraction to me. Whether I have to case-fold or not depends on the "encoding"/"version" of the scheme datums in a file and thus on the port.

Apart from that, reading the directive "!fold-case" from one port shouldn't affect any other port.

Chicken also has global parameters to treat [] and {} as parentheses, to support either :foo or foo: as a keyword (#:foo is always a keyword), and to support or not support symbols in vertical bars (which technically might have other uses in R5RS code).

The same goes for these parameters by the same reasons.