[Larceny-users] Ports' type changes unexpectedly

William D Clinger will at ccs.neu.edu
Thu Mar 19 19:36:38 EDT 2009


Derick Eddington wrote:
> > The R6RS library 8.2.6 specification of transcoded-port
> > says the closed binary port "cannot be used by the input
> > and output operations described in this chapter."
> 
> But that applies only to binary ports closed in the special way
> transcoded-port does, as the context of that quote makes clear.

No, I think the context of that quote makes it clear that,
even though the binary port has been closed in a special
way that might lead you to think it can still be used, it
is really just like all other closed ports in being unusable
by input and output operations.

> I don't
> see how it applies to any other closed ports.  Even if it could be
> construed to apply, "cannot be used by the input and output operations"
> doesn't mean the types of ports must change.

Scheme is not a typed language.  Certain properties of an
object are immutable, but others may be mutable.  Whether
something is a port, for example, is immutable, so it is
reasonable to think of that property as a type property.

Whether a port is open, on the other hand, is a mutable
property of a port.  Closing a port has major side effects.

The question here is whether the property of being an
input, output, binary, or textual port is mutable or
immutable.  The R6RS documents are certainly not as
clear about this as they should be, but I believe that,
considered in context, R6RS library 8.2.6 is saying that
the binary port that is closed by transcoded-port is like
other closed ports in that it can no longer be used for
input or output operations.

My opinion is not authoritative, but I did indeed write
the specification of transcoded-port (during the second
of two hurried rewrites of the R6RS library section 8.2
that I was asked to do on very short notice, even though
I wasn't on the io subcommittee).

Furthermore David Bartley and I designed and specified
the io system of RRRS, which survives in the R5RS and in
(rnrs io simple).  I see nothing in the R6RS documents
to indicate that the property of being an input or output
port has become immutable, after all these years of being
mutable in the RRRS through IEEE/ANSI and R5RS standards.

In particular, the disjoint types listed in R6RS 11.1 are
exactly the same as the ones listed in IEEE Standard 1178
section 3.4, Disjointness of Types.  A search for the word
"type" in R6RS library chapter 8 shows that the word is
almost always used in connection with condition types, and
there is absolutely no suggestion that the property of
being an input port (etc) has become an immutable property
of a port.  As the author of the last paragraph of R6RS
library 8.2, I'm pretty sure it was never intended to
suggest that any of those properties were immutable.

> port-eof? "returns #t if the lookahead-u8 procedure (if input-port is a
> binary port) or the lookahead-char procedure (if input-port is a textual
> port) would return the end-of-file object, and #f otherwise."  If a
> closed port, which is still an input port and is still either binary or
> textual, is given, I think it's clear that port-eof? returns #F (which
> Ikarus does, PLT does not, and Ypsilon does not) because lookahead-u8 or
> lookahead-char would not return the end-of-file object.

There may some way of reading the R6RS documents that would
allow an implementation to regard a closed port as an input
port, but I doubt it.  There is certainly no language that
would require a closed port to remain an input or output
port.

In Larceny, calling port-eof? on a closed input port raises
an exception:

> (define p (current-input-port))
> (close-port p)
> (port-eof? (current-input-port))
#f
> (port-eof? p)

Error: unhandled condition:
Compound condition has these components: 
#<record &assertion>
#<record &message>
    message : "assertion failed"
#<record &irritants>
    irritants : ((io/input-port? p))

As is typical of Larceny, the error message is poor, but the
reason for the exception is that (as R6RS library chapter 8
says) you aren't allowed to perform input or output opeations
on a closed port.  That semantics has been enforced in Larceny
for the past decade, and in Larceny's predecessor, MacScheme,
for another 15 years before that.  To my knowledge, none of
the thousands of users of those systems ever suggested that
a closed port should remain an input or output port.

> I still think it has too much potential to be seriously confusing.
> For what benefit?  It's confusing because...

It's confusing because you are thinking of type as an immutable
property of objects, which is okay so long as you use the word
"type" only when referring to immutable properties of objects.

Once you begin to use the word "type" to refer to mutable
properties, however, you will become confused.  The moral of
the story is that you shouldn't use the word "type" to refer
to properties of mutable objects unless the standards tell you
those properties are immutable---which is certainly not the
case here.

Just look at how often you're using the word "type" to refer
to properties that the R6RS documents are moderately careful
not to refer to as a "type".  You do that seven times in
your next two paragraphs:

> ... users get control flow based on
> "not a certain port type" but they're convinced the offending object
> must be a certain port type because they traced where it came from and
> they haven't discovered, memorized, and remembered that Larceny changes
> the type on them.  I'm glad I randomly noticed this instead of racking
> my brain for hours about how the hell could it not be a certain port
> type when a complex program breaks because of this.  I would much rather
> have a program break when it tries to perform I/O on a closed port and
> give me an exception saying "port is closed".
> 
> > and is less
> > confusing than having input ports for which port-eof?
> > would raise an exception or having output ports for which
> > flush-output-port would raise an exception.  
> 
> I don't understand this argument because by changing the types of closed
> ports to be an abstract androgynous type, the procedures with arguments
> which are required to be input or output or textual or binary ports will
> always raise an exception when given a closed port because the argument
> type is invalid.  How is this less confusing?

Once you learn not to refer to potentially mutable properties
as types, it will become much less confusing for you because
the properties will correspond exactly to what the R6RS says
about which arguments are accepted by the input and output
procedures.

If you persist in thinking of "input port" as an immutable
type, however, then you will have to invent some myth to
reconcile your thinking with the fact that closed ports are
not accepted by input operations that, according to the R6RS
library document, are required to accept input ports as
arguments.

Myths lead to confusion.  It's better to think clearly.

Will



More information about the Larceny-users mailing list