[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: output stream API
This page is part of the web mail archives of SRFI 68 from before July 7th, 2015. The new archives for SRFI 68 contain all messages, not just those from before July 7th, 2015.
>> 1. One specific thing that I just tripped
over: The return values of
>> output-bytes, output-char etc. are unspecified. Did I miss
>> something, or shouldn't they rather return the new stream, as
>> functional interface would?
> But there is no "new" stream---output streams are imperative.
> would be the point?
Example (?) for functional output streams:
A pretty printer take an object to pieces,
produces an output stream for each piece,
and composes its return value by
combining these streams---depending
on the properties of all pieces and all
streams. (Of couse this example is a
little simple-minded because pretty printing
is a little more complicated than that.)
In effect, functional output would be
just a way creating data structures storing
the result of converting something to
bytes. (In Ocaml, the 'Buffer' module, aka
extensible string buffers, is such a
thing---but of course it's state-based.)
Other question: If output streams are
imperative, what's the difference with output ports?
>> 4. One source of confusion for me is still
the read/write/display legacy
>> of Scheme that went into this SRFI.
> Huh? This SRFI *breaks* with that legacy. Could you be
I am referring to the READ/WRITE/DISPLAY
naming and meaning here.
The most useful classification for output
I came across is as follows:
O1. binary output for machine consumption
(e.g. writing a PNG-image),
O2. textual output suitable for machine
consumption but not fully unintelligible
(e.g. printing floats such that they
can be read back as they were), and
O3. human consumption only ('Hey, no
droids in this bar!'), e.g. printing
floats with a meaningful application-specific
number of decimal places.
For input, it comes down to reading
the different forms of output back in
(which can of course be complicated
and can also destroy information).
Now this distinction is not related
to the interface by which you input/output
the data (e.g. port or stream) but by
the intention you do that with---and by
the tools you need for that. This is
not fully reflected in the design of this
SRFI as far as I can see.
For O3. you need something like FORMAT
and for O1. you need a set
of tools for producing binary representations
for Scheme objects in a
controlled way (e.g. output-u8, output-u16-little
etc.). For O2 you still need
a way of producing textual representations
of Scheme objects.
The READ/WRITE/DISPLAY approach mixes
the tasks of converting
structured Scheme objects into bytes
and actually doing I/O. In SRFI-68
I have problems identifying the separation
as well (e.g. there is ouput-bytes
and output-string) and I find no reference
to where conversion tools will
come from (are they named "output-<type>"
or do they produce byte-
vectors all the time or what?).
It is generally a good idea not to try
to solve the conversion problem
and the actual I/O in one SRFI. But
the distinction/interface could be clearer.
>> 6. It would be great if there were a mechanism
specified for passing
>> additional arguments (options) between the levels.
> That's definitely true. At the time of
writing, I didn't have a good
> solution, so I stuck with using separate procedures for the common
> options. (I really dislike keyword arguments for various reasons.)
> have a better idea now, and I'll try to do something about the issue
> with the next revision.
Great! I do not care what the mechanism
looks like, if there is one that works.
> Having said that, note that I fully expect platform-specific
> to come up, as well as platform-specific methods for creating readers
> and writers. That's not inherently bad, given that the sets
> available options *are* platform-specific. It would be nice
> standardize on those as well, but they don't fall in the purview of
> this particular SRFI.
> (The SML Basis actually has a fourth, OS-specific layer, with variants
> for Unix and Windows.)
Ideally, the baseline functionality
is portable, i.e. read a textfile, read a binary
file, write a text file with create/overwrite,
and write a binary file with create/overwrite.
That's already revolutionary with respect
Beyond that I would either go for something
in which you can easily register
options at any time, or for something
using Scheme symbols.
Again, my point is not that every Scheme
implementation on Windows knows
how to start the high-throughput tape
recorder on the Cray (if it could only find it)
but that there is a heap allocated,
inspectable data structure for telling somebody.
For example: Scheme #1 on Windows and
Scheme #2 on the Cray talk to each
other. #1: "Tell me how you opened
the file, then." #2: (write '((tape . true) (encryption . off)
(user . surprise-mode) (floats . hashed-and-fried)))
#1: (define options-2 (read)) #2 exit
#3 (a new Scheme on the Cray) enter,
#3: "Hey #1, how did #2 open the file then?"
#1: (write options-2). #3: (define options
I don't particularly like symbols either
but they are good at carrying some
message from one place to another, while
all the intermediates have no
clue at all. (Symbols are just strings
with an efficient equality predicate.)
Long emails this...