[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
A few random I/O proposals
Date: Tue, 26 May 92 17:49:59 -0400
From: "Guillermo J. Rozas" <jinx@martigny.ai.mit.edu>
Reply-To: jinx@martigny.ai.mit.edu
* * It is impossible to open a file while allowing for the possibility
* that it might not be openable. The section on open-input-file says
* that "If the file cannot be opened, an error is signalled"; this may
* be okay for some circumstances, but there are times when you want
* something better than this. Two solutions that have been proposed are
* to have some other value be returned in this circumstance, #f being
* the obvious choice; or to allow the user some way to signal errors.
I object strongly to the "return #f" solution. It only leads to code
dying later in obscure ways because people forget to check.
An error/condition system can handle this reasonably well.
The current Scheme I/O system is a toy. It cannot handle read-write
files, positioning files, pipes, and other standard POSIX functions.
Earlier this year I got so annoyed with the Scheme I/O system that I
rewrote SCM's OPEN procedures in terms of ANSI_C/POSIX functions.
My functions return #f for failure. Despite dire warnings from
several people on comp.lang.scheme, I have NEVER been burnt by this
(and I make lots of mistakes). It is easy to write the Scheme
standard OPEN- functions in terms of OPEN-FILE. Here are my
definitions from Init.scm. COULD-NOT-OPEN handles the error condition
if it is defined.
(define (open-input-file str)
(or (open-file str OPEN_READ)
(and (procedure? could-not-open) (could-not-open) #f)
(error "OPEN-INPUT-FILE couldn't find file " str)))
(define (open-output-file str)
(or (open-file str OPEN_WRITE)
(and (procedure? could-not-open) (could-not-open) #f)
(error "OPEN-OUTPUT-FILE couldn't find file " str)))
(define close-input-port close-port)
(define close-output-port close-port)
(define (file-exists? str)
(let ((port (open-file str OPEN_READ)))
(if port (begin (close-port port) #t)
#f)))
(define load
(lambda (file)
(cond ((> (verbose) 0)
(display ";loading ")
(write file)
(newline)))
(force-output)
(or (try-load file)
;;HERE is where the suffix gets specified
(try-load (string-append file ".scm"))
(and (procedure? could-not-open) (could-not-open) #f)
(error "LOAD couldn't find file " file))
(set-errno! 0)
(cond ((> (verbose) 0)
(display ";done loading ")
(write file)
(newline)))))
(define could-not-open #f)
----------------------------------------------------------------------
If anyone is interested, here are my I/O functions:
(try-load <filename>) procedure
Filename should be a string. If filename names an existing file, the
try-load procedure reads Scheme source code expressions and
definintions from the file and evaluates them sequentially and returns
#t. If not, try-load returns #f. The try-load procedure does not
affect the values returned by current-input-port and current-output-port.
(open-file <string> <modes>) procedure
Returns a port capable of receiving or delivering characters as
specifie by the <modes> string. If a file cannot be opened #f is
returned.
OPEN_READ constant
OPEN_WRITE constant
OPEN_BOTH constant
Contain modes strings specifying that a file is to be opened for
reading, writing, and both reading and writing respectively.
(file-exists? <filename>) procedure
Returns #t if the specified file exists. Otherwise, returns #f.
(open-pipe <string> <modes>) procedure
If the string <modes> contains an "r" returns an input port capable of
delivering characters from the standard output of the system command
<string>. Otherwise, returns an output port capable of receiving
characters which become the standard input of the system command
<string>. If a pipe cannot be created #f is returned.
(close-pipe <pipe>) procedure
Closes the <pipe>, rendering it incapable of delivering or accepting
characters. This routine has no effect if the pipe has already been
closed. The value returned is unspecified.
(file-position <port>) procedure
Returns the current position of the character in <port> which will
next be read or written. If <port> is not open to a file the result
is unspecified.
(file-set-position <port> <integer>) procedure
Sets the current position in <port> which will next be read or
written. If <port> is not open to a file the action of
file-set-position is unspecified. The result of file-set-position is
unspecified.
(force-output) procedure
(force-output <port>) procedure
Forces any pending output on <port> to be delivered to the output
device and returns an unspecified value. The <port> argument may be
omitted, in which case it defaults to the value returned by
CURRENT-OUTPUT-PORT.
(read-string! <string>) procedure
(read-string! <string> <port>) procedure
Reads (string-length <string>) characters from <port>. If an end of
file is encountered during read-string! the characters up to that
point only are put into string (starting at the beginning) and the
remainder of the string is unchanged.
Read-string! returns the number of characters read. <Port> may be
omitted, in which case it defaults to the value returned by
current-input-port.
(chdir <filename>) procedure
Changes the current directory to <filename>. If <filename> does not
exist or is not a directory, #f is returned. Otherwise, #t is
returned.
(delete-file <filename>) procedure
Deletes the file specified by <filename>. If <filename> can not be
deleted, #f is returned. Otherwise, #t is returned.
(rename-file <oldfilename> <newfilename>) procedure
Renames the file specified by <oldfilename> to <newfilename>. If the
renaming is successful, #t is returned. Otherwise, #f is returned.