Skip to main content
Engineering LibreTexts

10.2: Streams vs. Collections

  • Page ID
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)

    The collection protocol supports the storage, removal and enumeration of the elements of a collection, but does not allow these operations to be intermingled. For example, if the elements of an OrderedCollection are processed by a do: method, it is not possible to add or remove elements from inside the do: block. Nor does the collection protocol offer ways to iterate over two collections at the same time, choosing which collection goes forward and which does not. Procedures like these require that a traversal index or position reference is maintained outside of the collection itself: this is exactly the role of ReadStream, WriteStream and ReadWriteStream.

    These three classes are defined to stream over some collection. For example, the following snippet creates a stream on an interval, then it reads two elements.

    r := ReadStream on: (1 to: 1000).
    r next.        →    1
    r next.        →    2
    r atEnd.       →    false

    WriteStreams can write data to the collection:

    w := WriteStream on: (String new: 5).
    w nextPut: $a.
    w nextPut: $b.
    w contents.    →    'ab'

    It is also possible to create ReadWriteStreams that support both the reading and writing protocols.

    The main problem with WriteStream and ReadWriteStream is that they only support arrays and strings in Squeak. This is currently being changed by the development of a new library named Nile, but for now if you try to stream over another kind of collection, you will get an error:

    w := WriteStream on: (OrderedCollection new: 20).
    w nextPut: 12.    →    raises an error 

    Streams are not only meant for collections, they can be used for files or sockets too. The following example creates a file named test.txt, writes two strings to it, separated by a carriage return, and closes the file.

        fileNamed: 'test.txt'
        do: [:str | str
            nextPutAll: '123';
            nextPutAll: 'abcd'].

    The following sections present the protocols in more depth.

    This page titled 10.2: Streams vs. Collections is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Andrew P. Black, Stéphane Ducasse, Oscar Nierstrasz, Damien Pollet via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.