[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

critical problems with call---file, with---file



Regarding these quotes from the latest revision:

 (under call-with-input-file, call-with-output-file)
    If the procedure returns, then the port is closed
    automatically and the value yielded by the procedure is
    returned.  If the procedure does not return, then Scheme
    will not close the port unless it can prove that the
    port will never again be used for a read or write operation.

 (under with-input-from-file, with-output-to-file)
    Furthermore, in contrast to call-with-input-file and
    call-with-output-file, these procedures will arrange to
    close the default port and restore the previous default
    whenever the system can prove that the call to the
    thunk will never return.


I have two problems with the wording of these two quotes.  One of
these probems can be ignored, and we'll only have an ill-specified
and confusing set of procedures.  The other cannot be ignored.


First, the one that cannot be ignored:  From the wording of the
second quote, it is technically possible (and perhaps required!)
for a Scheme system to close a port out from under a procedure in
a way we do not intend.  For example, if I write:
  (with-input-from-file "foo.in"
     (letrec ((loop (lambda ()
                       (write-char (read-char))
                       (loop))))
        loop)),
it is clear that a clever Scheme system can prove that the thunk
will never return; however, it would be entirely inappropriate to
close the new default port and restore the old.


The second problem takes a little more explaining:  I think that
most users will be very confused and rather upset that
call-with-input-file does not close the port automatically in the
case of a non-local exit, either programmed or through some sort
of error.  Also, in the case of with---file, it is not clear
whether an implementation is required to close the port as soon as
it can prove that the call will never return, or sometime thereafter.
Furthermore, it is not clear how sophisticated the system must be
in proving this fact.

In the most recent version of Chez Scheme, ports are closed by the
storage manager once it determines there is no possibility of
reference.  This will not necessarily occur as soon as the port
becomes inaccessible, but it is guaranteed that the system will not
run out of ports if there are any open, inaccessible ports around.
In addition, all ports are closed on exit from the system.  This
is a much more general and reasonable solution to the problem of
closing ports than forcing the programmer to use confusing,
ill-defined procedures that don't necessarily help in the case
of non-local exits or errors.

It is fine to say that the port is closed when the procedure or thunk
returns, but we should flush the descriptions of what happens when
the procedure or thunk does not return, perhaps mentioning that, in
order to avoid running out of file-system resources, implementations
usually close ports it can prove are inaccessible.  This would be
in the spirit of the earlier statement about not (usually!) running
out of storage (section 1.1, paragraph 4), and would also reinforce
the first-class status of ports.

Kent

p.s. We don't have much time, so please respond quickly.