3.14 Sequences
Sequence Constructors in Guide: PLT Scheme introduces sequences.
A sequence encapsulates an ordered stream of values. The elements of a sequence can be extracted with one of the for syntactic forms or with the procedures returned by sequence-generate.
The sequence datatype overlaps with many other datatypes. Among built-in datatypes, the sequence datatype includes the following:
lists (see Pairs and Lists)
vectors (see Vectors)
hash tables (see Hash Tables)
strings (see Strings)
byte strings (see Byte Strings)
input ports (see Ports)
In addition, make-do-sequence creates a sequence given a thunk that returns procedures to implement a generator, and the prop:sequence property can be associated with a structure type.
For most sequence types, extracting elements from a sequence has no side-effect on the original sequence value; for example, extracting the sequence of elements from a list does not change the list. For other sequence types, each extraction implies a side effect; for example, extracting the sequence of bytes from a port cause the bytes to be read from the port.
Inidvidual elements of a sequence typically correspond to single values, but an element may also correspond to multiple values. For example, a hash table generates two values – a key and its value – for each element in the sequence.
3.14.1 Sequence Predicate and Constructors
(in-range end) → sequence? |
end : number? |
(in-range start end [step]) → sequence? |
start : number? |
end : number? |
step : number? = 1 |
(in-naturals [start]) → sequence? |
start : exact-nonnegative-integer? = 0 |
(in-vector vec [start stop step]) → sequence? |
vec : vector? |
start : exact-nonnegative-integer? = 0 |
stop : (or/c exact-nonnegative-integer? #f) = #f |
step : (and/c exact-integer? (not/c zero?)) = 1 |
The optional arguments start, stop, and step are analogous to in-range, except that a #f value for stop is equivalent to (vector-length vec). That is, the first element in the sequence is (vector-ref vec start), and each successive element is generated by adding step to index of the previous element. The sequence stops before an index that would be greater or equal to end if step is non-negative, or less or equal to end if step is negative.
If start is less than stop and step is negative, then the exn:fail:contract:mismatch exception is raised. Similarly, if start is more than stop and step is positive, then the exn:fail:contract:mismatch exception is raised. The start and stop values are not checked against the size of vec, so access can fail when an element is demanded from the sequence.
An in-vector application can provide better performance for vector iteration when it appears directly in a for clause.
(in-string str [start stop step]) → sequence? |
str : string? |
start : exact-nonnegative-integer? = 0 |
stop : (or/c exact-nonnegative-integer? #f) = #f |
step : (and/c exact-integer? (not/c zero?)) = 1 |
The optional arguments start, stop, and step are as in in-vector.
An in-string application can provide better performance for string iteration when it appears directly in a for clause.
(in-bytes bstr [start stop step]) → sequence? |
bstr : bytes? |
start : exact-nonnegative-integer? = 0 |
stop : (or/c exact-nonnegative-integer? #f) = #f |
step : (and/c exact-integer? (not/c zero?)) = 1 |
The optional arguments start, stop, and step are as in in-vector.
An in-bytes application can provide better performance for byte string iteration when it appears directly in a for clause.
(in-input-port-bytes in) → sequence? |
in : input-port? |
(in-input-port-chars in) → sequence? |
in : input-port? |
(in-lines [in mode]) → sequence? | ||||||||||||
in : input-port? = (current-input-port) | ||||||||||||
|
(in-hash-keys hash) → sequence? |
hash : hash? |
(in-hash-values hash) → sequence? |
hash : hash? |
(in-hash-pairs hash) → sequence? |
hash : hash? |
(in-indexed seq) → sequence? |
seq : sequence? |
(in-sequences seq ) → sequence? |
seq : sequence? |
(in-parallel seq ) → sequence? |
seq : sequence? |
(make-do-sequence thunk) → sequence? | ||||||||||||
|
The thunk results define the generated elements as follows:
The first result is a pos->element procedure that takes the current position and returns the value(s) for the current element.
The second result is a next-pos procedure that takes the current position and returns the next position.
The third result is the initial position.
The fourth result takes the current position and returns a true result if the sequence includes the value(s) for the current position, and false if the sequence should end instead of including the value(s).
The fifth result is like the fourth result, but it takes the current element value(s) instead of the current position.
The sixth result is like the fourth result, but it takes both the current position and the current element values(s) and determines a sequence end after the current element is already included in the sequence.
Each of the procedures listed above is called only once per position. Among the last three procedures, as soon as one of the procedures returns #f, the sequence ends, and none are called again. Typically, one of the functions determines the end condition, and the other two functions always return #t.
Examples: | ||||||||||
| ||||||||||
| ||||||||||
(engine boxcar caboose) |