Issue: READ-AND-WRITE-BYTESReference: X3J13/92-102, dpANS 12.24
X3J13/92-2601, Jeremy Wertheimer comment #1
Category: ADDITION
Edit History: Version 1, 1/5/92, Kim Barrett
Status: Proposal NEW-FUNCTIONS passed (5+3)-3 on letter ballot 93-302.
Problem Description:
Common Lisp should have a facility for reading and writing blocks of
binary bytes. The lack of such a facility makes it impossible to write
portable efficient programs to access binary files. This lack might make
common lisp unsuitable for various applications such as database management
and image processing. This lack is not simply a matter of convenience that
could be remedied by user programming. If the standard does not provide at
least one method for efficiently reading and writing blocks of binary bytes,
users cannot later construct one using available common lisp facilities.
In addition, some users have complained about the lack of a non-consing
variant of READ-STRING, to which an existing string could be passed to receive
the data.
Proposal (READ-AND-WRITE-BYTES:NEW-FUNCTIONS):
Add the following dictionary entries to Chapter 21, Streams.
%%% ========== READ-SEQUENCE
\begincom{read-sequence}\ftype{Function}
\label Syntax::
\DefunWithValues {read-sequence} {sequence stream {\key} start end} {position}
\param{sequence}---a \term{sequence}.
\param{stream}---an \term{input} \term{stream}.
\param{start}, \param{end}---\term{bounding index designators} of
\param{sequence}. \Defaults{\param{start} and \param{end}}{\f{0} and \nil}
\param{position}---an \term{integer} greater than or equal to zero, and
less than or equal to the \term{length} of the \param{sequence}.
\label Description::
Destructively modifies \param{sequence} by replacing the \term{elements}
of \param{sequence} \term{bounded} by \param{start} and \param{end} with
\term{elements} read from \param{stream}.
\param{Sequence} is destructively modified by copying successive
\term{elements} into it from \param{stream}. If the \term{end of file} for
\param{stream} is reached before copying all \term{elements} of the
subsequence, then the extra \term{elements} near the end of \param{sequence}
are not updated.
\param{Position} is the index of the first \term{element} of \param{sequence}
that was not updated, which might be less than \param{end} because the
\term{end of file} was reached.
\label Examples::
\code
(defvar *data* (make-array 15 :initial-element nil))
(values (read-sequence *data* (make-string-input-stream "test string")) *data*)
\EV 11, #(#\t #\e #\s #\t #\Space #\s #\t #\r #\i #\n #\g NIL NIL NIL NIL)
\endcode
\label Side Effects::
Modifies \param{stream} and \param{sequence}.
\label Affected By:\None
\label Exceptional Situations::
\Lazychecktype{sequence}{a \term{proper sequence}}
\Shouldchecktype{start}{a non-negative \term{integer}}
\Shouldchecktype{end}{a non-negative \term{integer} or \nil}
Might signal an error \oftype{type-error} if an \term{element} read from
the \param{stream} is not a member of the \term{element type} of the
\param{sequence}.
\label See Also::
{\secref\ConstantModification}, \funref{write-sequence}, \funref{read-line}
\label Notes::
\funref{read-sequence} is identical in effect to iterating over the indicated
subsequence and reading one \term{element} at a time from \param{stream} and
storing it into \param{sequence}, but may be more efficient than the
equivalent loop. An efficient implementation is more likely to exist
for the case where the \param{sequence} is a \term{vector} with the same
\term{element type} as the \param{stream}.
%%% ========== WRITE-SEQUENCE
\begincom{write-sequence}\ftype{Function}
\label Syntax::
\DefunWithValues {write-sequence} {sequence stream {\key} start end} {sequence}
\param{sequence}---a \term{sequence}.
\param{stream}---an \term{output} \term{stream}.
\param{start}, \param{end}---\term{bounding index designators} of
\param{sequence}. \Defaults{\param{start} and \param{end}}{\f{0} and \nil}
\label Description::
\funref{write-sequence} writes the \term{elements} of the subsequence
of \param{sequence} \term{bounded} by \param{start} and \param{end} to
\param{stream}.
\label Examples::
\code
(write-sequence "bookworms" *standard-output* :end 4)
\OUT book
\EV "bookworms"
\endcode
\label Side Effects::
Modifies \param{stream}.
\label Affected By:\None
\label Exceptional Situations::
\Lazychecktype{sequence}{a \term{proper sequence}}
\Shouldchecktype{start}{a non-negative \term{integer}}
\Shouldchecktype{end}{a non-negative \term{integer} or \nil}
Might signal an error \oftype{type-error} if an \term{element} of the
\term{bounded} \term{sequence} is not a member of the
\term{stream element type} of the \param{stream}.
\label See Also::
{\secref\ConstantModification}, \funref{read-sequence}, \funref{write-string},
\funref{write-line}
\label Notes::
\funref{write-sequence} is identical in effect to iterating over the indicated
subsequence and writing one \term{element} at a time to \param{stream}, but
may be more efficient than the equivalent loop. An efficient implementation
is more likely to exist for the case where the \param{sequence} is a
\term{vector} with the same \term{element type} as the \param{stream}.
Editorial Impact:
Just drop in a couple more dictionary entries. Might want to add a few more
cross references.
Rationale:
Addresses the problem description.
Current Practice:
Symbolics Genera provides :string-in and :string-out operations on streams
that could easily be used to implement these functions.
IIM Common Lisp provides functions with similar capabilities but under
slightly different names.
Cost to Implementors:
Depends on the details of the implementation of the stream operators, but
probably not very difficult in most cases. Getting maximum efficiency might
require some significant work, but some of that work has probably already
been done to support existing operators or extensions.
Cost to Users:
None. This is an upwardly compatible addition.
Performance Impact:
Some existing code that uses iteration could be rewritten to use the new
operators, with a potentially substantial improvement in performance.
Benefits:
Improved performance, and clearer code.
Aesthetics:
The use of these operators is probably clearer than the corresponding
iteration code, and therefor more aesthetic.