Slate's collection hierarchy makes use of composing multiple behaviors (via inheritance) to provide a collection system that can be reasoned about with greater certainty, and that can be extended more easily than other object-oriented languages' collection types. Primarily Slate collections are mutable, which means that basic modifications occur destructively on the collection object.
Figure 2 shows the overview of the collection types, and how their inheritance is patterned.
All collections support a minimal set of methods, including support for basic internal iteration and testing. The following are representative core methods, and are by no means the limit of collection features:
Collections derived from ExtensibleCollection can be modified by adding or removing elements in various ways. The core protocol is:
Sequences are Mappings from a range of natural numbers to some objects, sometimes restricted to a given type. Slate sequences are all addressed from a base of 0.
Arrays are fixed-length sequences of any kind of object and are supported primitively. Various parameter types of Array are supported primitively, such as WordArray, ByteArray, and String.
Vectors and Tuples are fixed-length sequences constructed for geometrical purposes. Points happen to be Tuples. The constructor message for these types is ``,''.
Subsequences allow one to treat a segment of a sequence as a separate sequence with its own addressing scheme; however, modifying the subsequence will cause the original to be modified.
Cords are a non-copying representation of a concatenation of Sequences. Normal concatenation of Sequences is performed with the ; method, and results in copying both of the arguments into a new Sequence of the appropriate type; the ;; method will construct a Cord instead. They efficiently implement accessing via at: and iteration via do:, and Cord as: Sequence will ``flatten'' the Cord into a Sequence.
An ExtensibleSequence is an extensible Sequence with some special methods to treat both ends as queues. It provides the following additional protocol:
A Stack is an ExtensibleSequence augmented with methods to honor the stack abstraction: push:, pop, top, etc.
A Range is a Sequence of Numbers between two values, that is ordered consecutively and has some stepping value; they include the start value and also the end value unless the stepping doesn't lead to the end value exactly, in which case the last value is the greatest value in the sequence that is still before the end marker value. Creating ranges is identical to the numeric iteration protocol in 3.5.4, without the final do: keyword, and sending the do: message to a Range performs the identical function.
A RingBuffer is a special ExtensibleSequence that takes extra care to only use one underlying array object, and also stores its elements in a ``wrap-around'' fashion, to make for an efficient queue for Streams (see ReadBufferStream and WriteBufferStream (des:ReadBufferStream)). One consequence of this is that a RingBuffer has a limited upper bound in size which the client must handle, although the capacity can be grown explicitly.
Strings in Slate are non-extensible, mutable Sequences of Characters (although ExtensibleSequences can easily be made for them via, say, as:). Strings and Characters have a special literal syntax, and methods specific to dealing with text; most of the useful generic methods for strings are lifted to the Sequence type. Strings provide the following specific protocol:
NoDuplicatesCollection forms a special protocol that allows for extension in a well-mannered way. Instead of an add: protocol for extension, these collections provide include:, which ensures that at least one element of the collection is the target object, but doesn't do anything otherwise. Using include: will never add an object if it is already present. These collection types still respond to add: and its variants, but they will behave in terms of the include: semantics.
The default implementation of this protocol is Set, which stores its elements in a (somewhat sparse) hashed array.
Mappings provide a general protocol for associating the elements of a set of keys each to a value object. A Dictionary is essentially a Set of these Associations, but they are generally used with Symbols as keys.
Mapping defines the general protocol at: and at:put: that Sequences use, which also happen to be Mappings. Mappings also support iteration protocols such as keysDo:, valuesDo:, and keysAndValuesDo:.
A LinkedCollection provides a type of collection where the elements themselves are central to defining what is in the collection and what is not.
The usual LinkedList type, comprised of individual Links with forward and backward directional access, is provided as a flexible but basic data structure. This type does require that its elements follow the Link protocol, however, so it does require some advanced preparation to use it.
Slate includes libraries for binary trees, red-black trees, trees with ordered elements, and tries.
A directed graph, or Digraph (directed graph) type, is provided with associated Node and Edge types. A KeyedDigraph provides the same behavior with a keyed access, similar to that in a Mapping, although there is an allowance for various kinds of non-determinism, which makes this useful for creating Non-deterministic Finite Automata.
Slate includes the beginnings of a mathematical vector and matrix library. See the 'src/lib/matrix.slate' file for an overview.