#

## Issue READ-AND-WRITE-BYTES Writeup

    Issue:        READ-AND-WRITE-BYTES
    Reference:    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.

Copyright 1996-2005, LispWorks Ltd. All rights reserved.