4.17.1 Sequences

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

► | 4 | Datatypes

4.1 | Equality
4.2 | Booleans
4.3 | Numbers
4.4 | Strings
4.5 | Byte Strings
4.6 | Characters
4.7 | Symbols
4.8 | Regular Expressions
4.9 | Keywords
4.10 | Pairs and Lists
4.11 | Mutable Pairs and Lists
4.12 | Vectors
4.13 | Stencil Vectors
4.14 | Boxes
4.15 | Hash Tables
4.16 | Treelists
4.17 | Sequences and Streams
4.18 | Dictionaries
4.19 | Sets
4.20 | Procedures
4.21 | Void
4.22 | Undefined

▼ | 4.17 | Sequences and Streams

4.17.1 | Sequences
4.17.2 | Streams
4.17.3 | Generators

► | 4.17.1 | Sequences

4.17.1.1 | Sequence Predicate and Constructors
4.17.1.2 | Sequence Conversion
4.17.1.3 | Additional Sequence Operations

On this page:

4.17.1.1`` Sequence Predicate and Constructors
sequence?
in-range
in-inclusive-range
in-naturals
in-list
in-mlist
in-vector
in-string
in-bytes
in-port
in-input-port-bytes
in-input-port-chars
in-lines
in-bytes-lines
in-hash
in-hash-keys
in-hash-values
in-hash-pairs
in-mutable-hash
in-mutable-hash-keys
in-mutable-hash-values
in-mutable-hash-pairs
in-immutable-hash
in-immutable-hash-keys
in-immutable-hash-values
in-immutable-hash-pairs
in-weak-hash
in-weak-hash-keys
in-weak-hash-values
in-weak-hash-pairs
in-ephemeron-hash
in-ephemeron-hash-keys
in-ephemeron-hash-values
in-ephemeron-hash-pairs
in-directory
in-producer
in-value
in-indexed
in-sequences
in-cycle
in-parallel
in-values-sequence
in-values*-sequence
stop-before
stop-after
make-do-sequence
prop: sequence
4.17.1.2`` Sequence Conversion
sequence->stream
sequence-generate
sequence-generate*
4.17.1.3`` Additional Sequence Operations
empty-sequence
sequence->list
sequence-length
sequence-ref
sequence-tail
sequence-append
sequence-map
sequence-andmap
sequence-ormap
sequence-for-each
sequence-fold
sequence-count
sequence-filter
sequence-add-between
sequence/ c
4.17.1.3.1`` Additional Sequence Constructors and Functions
in-syntax
in-slice
initiate-sequence

top contents ← prev up next →

##### 4.17.1`` Sequences🔗ℹ

> > > Sequence Constructors in The Racket Guide introduces sequences.

A sequence encapsulates an ordered collection of values. The elements of a sequence can be extracted with one of the for syntactic forms, with the procedures returned by sequence-generate, or by converting the sequence into a stream.

The sequence datatype overlaps with many other datatypes. Among built-in datatypes, the sequence datatype includes the following:

- exact nonnegative integers (see below)

- strings (see Strings)

- byte strings (see Byte Strings)

- lists (see Pairs and Lists)

- mutable lists (see Mutable Pairs and Lists)

- vectors (see Vectors)

- flvectors (see Flonum Vectors)

- fxvectors (see Fixnum Vectors)

- hash tables (see Hash Tables)

- dictionaries (see Dictionaries)

- sets (see Sets)

- input ports (see Ports)

- streams (see Streams)

An exact number k that is a non-negative integer acts as a sequence similar to (in-range k), except that k by itself is not a stream.

Custom sequences can be defined using structure type properties. The easiest method to define a custom sequence is to use the gen:stream generic interface. Streams are a suitable abstraction for data structures that are directly iterable. For example, a list is directly iterable with first and rest. On the other hand, vectors are not directly iterable: iteration has to go through an index. For data structures that are not directly iterable, the iterator for the data structure can be defined to be a stream (e.g., a structure containing the index of a vector).

For example, unrolled linked lists (represented as a list of vectors) themselves do not fit the stream abstraction, but have index-based iterators that can be represented as streams:

Examples:

> > (struct unrolled-list-iterator (idx lst)
> #:methods gen:stream
> [(define (stream-empty? iter)
> (define lst (unrolled-list-iterator-lst iter))
> (or (null? lst)
> (and (>= (unrolled-list-iterator-idx iter)
> (vector-length (first lst)))
> (null? (rest lst)))))
> (define (stream-first iter)
> (vector-ref (first (unrolled-list-iterator-lst iter))
> (unrolled-list-iterator-idx iter)))
> (define (stream-rest iter)
> (define idx (unrolled-list-iterator-idx iter))
> (define lst (unrolled-list-iterator-lst iter))
> (if (>= idx (sub1 (vector-length (first lst))))
> (unrolled-list-iterator 0 (rest lst))
> (unrolled-list-iterator (add1 idx) lst)))])
> > (define (make-unrolled-list-iterator ul)
> (unrolled-list-iterator 0 (unrolled-list-lov ul)))
> > (struct unrolled-list (lov)
> #:property prop:sequence
> make-unrolled-list-iterator)
> > (define ul1 (unrolled-list '(#(cracker biscuit) #(cookie scone))))
> > (for/list ([x ul1]) x)
> '(cracker biscuit cookie scone)

The prop:sequence property provides more flexibility in specifying iteration, such as when a pre-processing step is needed to prepare the data for iteration. The make-do-sequence function creates a sequence given a thunk that returns procedures to implement a sequence, and the prop:sequence property can be associated with a structure type to implement its implicit conversion to a sequence.

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 causes the bytes to be read from the port. A sequence’s state may either span all uses of the sequence, as for a port, or it may be confined to each distinct time that a sequence is initiated by a for form, sequence->stream, sequence-generate, or sequence-generate*. Concretely, the thunk passed to make-do-sequence is called to initiate the sequence each time the sequence is used. Accordingly, different sequences behave differently when they are initiated multiple times.

> > (define (double-initiate s1)
> ; initiate the sequence twice
> (define-values (more?.1 next.1) (sequence-generate s1))
> (define-values (more?.2 next.2) (sequence-generate s1))
> ; alternate fetching from sequence via the two initiations
> (list (next.1) (next.2) (next.1) (next.2)))
> > (double-initiate (open-input-string "abcdef"))
> '(97 98 99 100)
> > (double-initiate (list 97 98 99 100))
> '(97 97 98 98)
> > (double-initiate (in-naturals 97))
> '(97 97 98 98)

Also, subsequent elements in a sequence may be “consumed” just by calling the first result of sequence-generate, even if the second result is never called.

> > (define (double-initiate-and-use-more? s1)
> ; initiate the sequence twice
> (define-values (more?.1 next.1) (sequence-generate s1))
> (define-values (more?.2 next.2) (sequence-generate s1))
> ; alternate fetching from sequence via the two initiations
> ; but this time call `more?` in between
> (list (next.1) (more?.1) (next.2) (more?.2)
> (next.1) (more?.1) (next.2) (more?.2)))
> > (double-initiate-and-use-more? (open-input-string "abcdef"))
> '(97 #t 99 #t 98 #t 100 #t)

In this example, the state embedded in the first call to sequence-generate “takes” the 98 just by virtue of the invocation of more?.1.

Individual 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.

##### 4.17.1.1`` Sequence Predicate and Constructors🔗ℹ

> procedure (sequence? v) → boolean?
> v : any/c

Returns #t if v can be used as a sequence, #f otherwise.

Examples:

> > (sequence? 42)
> #t
> > (sequence? '(a b c))
> #t
> > (sequence? "word")
> #t
> > (sequence? #\x)
> #f

> procedure (in-range end) → stream?
> end : real?
> (in-range start end [step]) → stream?
> start : real?
> end : real?
> step : real? = 1

Returns a sequence (that is also a stream) whose elements are numbers. The single-argument case (in-range end) is equivalent to (in-range 0 end 1). The first number in the sequence is start, and each successive element is generated by adding step to the previous element. The sequence stops before an element that would be greater or equal to end if step is non-negative, or less or equal to end if step is negative.
An in-range application can provide better performance for number iteration when it appears directly in a for clause.

Example: gaussian sum

> > (for/sum ([x (in-range 10)]) x)
> 45

Example: sum of even numbers

> > (for/sum ([x (in-range 0 100 2)]) x)
> 2450

When given zero as step, in-range returns an infinite sequence. It may also return infinite sequences when step is a very small number, and either step or the sequence elements are floating-point numbers.

> procedure (in-inclusive-range start end [step]) → stream?
> start : real?
> end : real?
> step : real? = 1

Similar to in-range, but the sequence stopping condition is changed so that the last element is allowed to be equal to end.
An in-inclusive-range application can provide better performance for number iteration when it appears directly in a for clause.

Examples:

> > (sequence->list (in-inclusive-range 7 11))
> '(7 8 9 10 11)
> > (sequence->list (in-inclusive-range 7 11 2))
> '(7 9 11)
> > (sequence->list (in-inclusive-range 7 10 2))
> '(7 9)

Added in version 8.0.0.13 of package base.

> procedure (in-naturals [start]) → stream?
> start : exact-nonnegative-integer? = 0

Returns an infinite sequence (that is also a stream) of exact integers starting with start, where each element is one more than the preceding element.
An in-naturals application can provide better performance for integer iteration when it appears directly in a for clause.

Example:

> > (for/list ([k (in-naturals)]
> [x (in-range 10)])
> (list k x))
> '((0 0) (1 1) (2 2) (3 3) (4 4) (5 5) (6 6) (7 7) (8 8) (9 9))

> procedure (in-list lst) → stream?
> lst : list?

Returns a sequence (that is also a stream) that is equivalent to using lst directly as a sequence.

> > > See Pairs and Lists for information on using lists as sequences.

An in-list application can provide better performance for list iteration when it appears directly in a for clause.
See for for information on the reachability of list elements during an iteration.

Example:

> > (for/list ([x (in-list '(3 1 4))])
> `(,x ,(* x x)))
> '((3 9) (1 1) (4 16))

Changed in version 6.7.0.4 of package base: Improved element-reachability guarantee for lists in for.

> procedure (in-mlist mlst) → sequence?
> mlst : mlist?

Returns a sequence equivalent to mlst. Although the expectation is that mlst is mutable list, in-mlist initially checks only whether mlst is a mutable pair or null, since it could change during iteration.

> > > See Mutable Pairs and Lists for information on using mutable lists as sequences.

An in-mlist application can provide better performance for mutable list iteration when it appears directly in a for clause.

Example:

> > (for/list ([x (in-mlist (mcons "RACKET" (mcons "LANG" '())))])
> (string-length x))
> '(6 4)

> procedure (in-vector vec [start stop step]) → sequence?
> vec : vector?
> start : exact-nonnegative-integer? = 0
> stop : (or/c exact-integer? #f) = #f
> step : (and/c exact-integer? (not/c zero?)) = 1

Returns a sequence equivalent to vec when no optional arguments are supplied.

> > > See Vectors for information on using vectors as sequences.

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 not a valid index, then the exn:fail:contract exception is raised, except when start, stop, and (vector-length vec) are equal, in which case the result is an empty sequence.

Examples:

> > (for ([x (in-vector (vector 1) 1)]) x)
> > (for ([x (in-vector (vector 1) 2)]) x)
> in-vector: starting index is out of range
> starting index: 2
> valid range: [0, 0]
> vector: '#(1)
> > (for ([x (in-vector (vector) 0 0)]) x)
> > (for ([x (in-vector (vector 1) 1 1)]) x)

If stop is not in [-1, (vector-length vec)], then the exn:fail:contract exception is raised.

If start is less than stop and step is negative, then the exn:fail:contract exception is raised. Similarly, if start is more than stop and step is positive, then the exn:fail:contract exception is raised.

An in-vector application can provide better performance for vector iteration when it appears directly in a for clause.

Examples:

> > (define (histogram vector-of-words)
> (define a-hash (make-hash))
> (for ([word (in-vector vector-of-words)])
> (hash-set! a-hash word (add1 (hash-ref a-hash word 0))))
> a-hash)
> > (histogram #("hello" "world" "hello" "sunshine"))
> '#hash(("hello" . 2) ("sunshine" . 1) ("world" . 1))

> procedure (in-string str [start stop step]) → sequence?
> str : string?
> start : exact-nonnegative-integer? = 0
> stop : (or/c exact-integer? #f) = #f
> step : (and/c exact-integer? (not/c zero?)) = 1

Returns a sequence equivalent to str when no optional arguments are supplied.

> > > See Strings for information on using strings as sequences.

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.

Examples:

> > (define (line-count str)
> (for/sum ([ch (in-string str)])
> (if (char=? #\newline ch) 1 0)))
> > (line-count "this string\nhas\nthree \nnewlines")
> 3

> procedure (in-bytes bstr [start stop step]) → sequence?
> bstr : bytes?
> start : exact-nonnegative-integer? = 0
> stop : (or/c exact-integer? #f) = #f
> step : (and/c exact-integer? (not/c zero?)) = 1

Returns a sequence equivalent to bstr when no optional arguments are supplied.

> > > See Byte Strings for information on using byte strings as sequences.

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.

Examples:

> > (define (has-eof? bs)
> (for/or ([ch (in-bytes bs)])
> (= ch 0)))
> > (has-eof? #"this byte string has an \0embedded zero byte")
> #t
> > (has-eof? #"this byte string does not")
> #f

> procedure (in-port [r in]) → sequence?
> r : (input-port? . -> . any/c) = read
> in : input-port? = (current-input-port)

Returns a sequence whose elements are produced by calling r on in until it produces eof.

> procedure (in-input-port-bytes in) → sequence?
> in : input-port?

Returns a sequence equivalent to (in-port read-byte in).

> procedure (in-input-port-chars in) → sequence?
> in : input-port?

Returns a sequence whose elements are read as characters from in (equivalent to (in-port read-char in)).

> procedure (in-lines [in mode]) → sequence?
> in : input-port? = (current-input-port)
> | mode |  | : |  | (or/c 'linefeed 'return 'return-linefeed 'any 'any-one)
> |  |  | = |  | 'any

Returns a sequence equivalent to (in-port (lambda (p) (read-line p mode)) in). Note that the default mode is 'any, whereas the default mode of read-line is 'linefeed.

> procedure (in-bytes-lines [in mode]) → sequence?
> in : input-port? = (current-input-port)
> | mode |  | : |  | (or/c 'linefeed 'return 'return-linefeed 'any 'any-one)
> |  |  | = |  | 'any

Returns a sequence equivalent to (in-port (lambda (p) (read-bytes-line p mode)) in). Note that the default mode is 'any, whereas the default mode of read-bytes-line is 'linefeed.

> procedure (in-hash hash) → sequence?
> hash : hash?
> (in-hash hash bad-index-v) → sequence?
> hash : hash?
> bad-index-v : any/c

Returns a sequence equivalent to hash, except when bad-index-v is supplied.

If bad-index-v is supplied, then bad-index-v is returned as both the key and the value in the case that the hash is modified concurrently so that iteration does not have a valid hash index. Providing bad-index-v is particularly useful when iterating through a hash table with weakly held keys, since entries can be removed asynchronously (i.e., after in-hash has committed to another iteration, but before it can access the entry for the next iteration).

Examples:

> > (define table (hash 'a 1 'b 2))
> > (for ([(key value) (in-hash table)])
> (printf "key: ~a value: ~a\n" key value))
> key: b value: 2
> key: a value: 1

> > > See Hash Tables for information on using hash tables as sequences.

Changed in version 7.0.0.10 of package base: Added the optional bad-index-v argument.

> procedure (in-hash-keys hash) → sequence?
> hash : hash?
> (in-hash-keys hash bad-index-v) → sequence?
> hash : hash?
> bad-index-v : any/c

Returns a sequence whose elements are the keys of hash, using bad-index-v in the same way as in-hash.

Examples:

> > (define table (hash 'a 1 'b 2))
> > (for ([key (in-hash-keys table)])
> (printf "key: ~a\n" key))
> key: b
> key: a

Changed in version 7.0.0.10 of package base: Added the optional bad-index-v argument.

> procedure (in-hash-values hash) → sequence?
> hash : hash?
> (in-hash-values hash bad-index-v) → sequence?
> hash : hash?
> bad-index-v : any/c

Returns a sequence whose elements are the values of hash, using bad-index-v in the same way as in-hash.

Examples:

> > (define table (hash 'a 1 'b 2))
> > (for ([value (in-hash-values table)])
> (printf "value: ~a\n" value))
> value: 2
> value: 1

Changed in version 7.0.0.10 of package base: Added the optional bad-index-v argument.

> procedure (in-hash-pairs hash) → sequence?
> hash : hash?
> (in-hash-pairs hash bad-index-v) → sequence?
> hash : hash?
> bad-index-v : any/c

Returns a sequence whose elements are pairs, each containing a key and its value from hash (as opposed to using hash directly as a sequence to get the key and value as separate values for each element).

The bad-index-v argument, if supplied, is used in the same way as by in-hash. When an invalid index is encountered, the pair in the sequence with have bad-index-v as both its car and cdr.

Examples:

> > (define table (hash 'a 1 'b 2))
> > (for ([key+value (in-hash-pairs table)])
> (printf "key and value: ~a\n" key+value))
> key and value: (b . 2)
> key and value: (a . 1)

Changed in version 7.0.0.10 of package base: Added the optional bad-index-v argument.

> procedure (in-mutable-hash hash) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> procedure (in-mutable-hash hash bad-index-v) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> bad-index-v : any/c
> procedure (in-mutable-hash-keys hash) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> procedure (in-mutable-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> bad-index-v : any/c
> procedure (in-mutable-hash-values hash) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> procedure (in-mutable-hash-values hash bad-index-v) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> bad-index-v : any/c
> procedure (in-mutable-hash-pairs hash) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> procedure (in-mutable-hash-pairs hash bad-index-v) → sequence?
> hash : (and/c hash? (not/c immutable?) hash-strong?)
> bad-index-v : any/c
> procedure (in-immutable-hash hash) → sequence?
> hash : (and/c hash? immutable?)
> procedure (in-immutable-hash hash bad-index-v) → sequence?
> hash : (and/c hash? immutable?)
> bad-index-v : any/c
> procedure (in-immutable-hash-keys hash) → sequence?
> hash : (and/c hash? immutable?)
> procedure (in-immutable-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? immutable?)
> bad-index-v : any/c
> procedure (in-immutable-hash-values hash) → sequence?
> hash : (and/c hash? immutable?)
> procedure (in-immutable-hash-values hash bad-index-v) → sequence?
> hash : (and/c hash? immutable?)
> bad-index-v : any/c
> procedure (in-immutable-hash-pairs hash) → sequence?
> hash : (and/c hash? immutable?)
> procedure (in-immutable-hash-pairs hash bad-index-v) → sequence?
> hash : (and/c hash? immutable?)
> bad-index-v : any/c
> procedure (in-weak-hash hash) → sequence?
> hash : (and/c hash? hash-weak?)
> procedure (in-weak-hash hash bad-index-v) → sequence?
> hash : (and/c hash? hash-weak?)
> bad-index-v : any/c
> procedure (in-weak-hash-keys hash) → sequence?
> hash : (and/c hash? hash-weak?)
> procedure (in-weak-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? hash-weak?)
> bad-index-v : any/c
> procedure (in-weak-hash-values hash) → sequence?
> hash : (and/c hash? hash-weak?)
> procedure (in-weak-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? hash-weak?)
> bad-index-v : any/c
> procedure (in-weak-hash-pairs hash) → sequence?
> hash : (and/c hash? hash-weak?)
> procedure (in-weak-hash-pairs hash bad-index-v) → sequence?
> hash : (and/c hash? hash-weak?)
> bad-index-v : any/c
> procedure (in-ephemeron-hash hash) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> procedure (in-ephemeron-hash hash bad-index-v) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> bad-index-v : any/c
> procedure (in-ephemeron-hash-keys hash) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> procedure (in-ephemeron-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> bad-index-v : any/c
> procedure (in-ephemeron-hash-values hash) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> procedure (in-ephemeron-hash-keys hash bad-index-v) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> bad-index-v : any/c
> procedure (in-ephemeron-hash-pairs hash) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> procedure (in-ephemeron-hash-pairs hash bad-index-v) → sequence?
> hash : (and/c hash? hash-ephemeron?)
> bad-index-v : any/c

Sequence constructors for specific kinds of hash tables. These may perform better than the analogous in-hash forms.

Added in version 6.4.0.6 of package base.
Changed in version 7.0.0.10: Added the optional bad-index-v argument.
Changed in version 8.0.0.10: Added ephemeron variants.

> procedure (in-directory [dir use-dir?]) → (sequence/c path?)
> dir : (or/c #f path-string?) = #f
> | use-dir? |  | : |  | ((and/c path? complete-path?) . -> . any/c)
> |  |  | = |  | (lambda (dir-path) #t)

Returns a sequence that produces all of the paths for files, directories, and links within dir, except for the contents of any directory for which use-dir? returns #f. If dir is not #f, then every produced path starts with dir as its prefix. If dir is #f, then paths in and relative to the current directory are produced.

An in-directory sequence traverses nested subdirectories recursively (filtered by use-dir?). To generate a sequence that includes only the immediate content of a directory, use the result of directory-list as a sequence.

The immediate content of each directory is reported as sorted by path<?, and the content of a subdirectory is reported before subsequent paths within the directory.

Examples:

> > (current-directory (path-only (collection-file-path "main.rkt" "info")))
> > (for/list ([f (in-directory)])
> f)
> '(#<path:compiled>
> #<path:compiled/main_rkt.dep>
> #<path:compiled/main_rkt.zo>
> #<path:main.rkt>)
> > (for/list ([f (in-directory "compiled")])
> f)
> '(#<path:compiled/main_rkt.dep> #<path:compiled/main_rkt.zo>)
> > (for/list ([f (in-directory #f (lambda (p)
> (not (regexp-match? #rx"compiled" p))))])
> f)
> '(#<path:compiled> #<path:main.rkt>)

Changed in version 6.0.0.1 of package base: Added use-dir? argument.
Changed in version 6.6.0.4: Added guarantee of sorted results.

> procedure (in-producer producer) → sequence?
> producer : procedure?
> (in-producer producer stop arg ...) → sequence?
> producer : procedure?
> stop : any/c
> arg : any/c

Returns a sequence that contains values from sequential calls to producer, which would usually use some state to do its work.

If a stop value is not given, the sequence goes on infinitely, and therefore it is common to use it with a finite sequence or using #:break etc. If a stop value is given, it is used to identify a value that marks the end of the sequence (and the stop value is not included in the sequence); stop can be a predicate that is applied to the results of producer, or it can be a value that is tested against the result of with eq?. (The stop argument must be a predicate if the stop value is itself a function or if producer returns multiple values.)

If additional args are specified, they are passed to every call to producer.

Examples:

> > (define (counter)
> (define n 0)
> (lambda ([d 1]) (set! n (+ d n)) n))
> > (for/list ([x (in-producer (counter))] [y (in-range 4)]) x)
> '(1 2 3 4)
> > (for/list ([x (in-producer (counter))] #:break (= x 5)) x)
> '(1 2 3 4)
> > (for/list ([x (in-producer (counter) 5)]) x)
> '(1 2 3 4)
> > (for/list ([x (in-producer (counter) 5 1/2)]) x)
> '(1/2 1 3/2 2 5/2 3 7/2 4 9/2)
> > (for/list ([x (in-producer read eof (open-input-string "1 2 3"))]) x)
> '(1 2 3)

> procedure (in-value v) → sequence?
> v : any/c

Returns a sequence that produces a single value: v.

This form is mostly useful for let-like bindings in forms such as for*/list—but a #:do clause form, added more recently, covers many of the same uses.

> procedure (in-indexed seq) → sequence?
> seq : sequence?

Returns a sequence where each element has two values: the value produced by seq, and a non-negative exact integer starting with 0. The elements of seq must be single-valued.

Example:

> > (for ([(ch i) (in-indexed "hello")])
> (printf "The char at position ~a is: ~a\n" i ch))
> The char at position 0 is: h
> The char at position 1 is: e
> The char at position 2 is: l
> The char at position 3 is: l
> The char at position 4 is: o

> procedure (in-sequences seq ...) → sequence?
> seq : sequence?

Returns a sequence that is made of all input sequences, one after the other. Each seq is initiated only after the preceding seq is exhausted. If a single seq is provided, then seq is returned; otherwise, the elements of each seq must all have the same number of values.

> procedure (in-cycle seq ...) → sequence?
> seq : sequence?

Similar to in-sequences, but the sequences are repeated in an infinite cycle, where each seq is initiated afresh in each iteration. Beware that if no seqs are provided or if all seqs become empty, then the sequence produced by in-cycle never returns when an element is demanded—or even when the sequence is initiated, if all seqs are initially empty.

> procedure (in-parallel seq ...) → sequence?
> seq : sequence?

Returns a sequence where each element has as many values as the number of supplied seqs; the values, in order, are the values of each seq. The elements of each seq must be single-valued.

> procedure (in-values-sequence seq) → sequence?
> seq : sequence?

Returns a sequence that is like seq, but it combines multiple values for each element from seq as a list of elements.

> procedure (in-values*-sequence seq) → sequence?
> seq : sequence?

Returns a sequence that is like seq, but when an element of seq has multiple values or a single list value, then the values are combined in a list. In other words, in-values*-sequence is like in-values-sequence, except that non-list, single-valued elements are not wrapped in a list.

> procedure (stop-before seq pred) → sequence?
> seq : sequence?
> pred : (any/c . -> . any)

Returns a sequence that contains the elements of seq (which must be single-valued), but only until the last element for which applying pred to the element produces #t, after which the sequence ends.

> procedure (stop-after seq pred) → sequence?
> seq : sequence?
> pred : (any/c . -> . any)

Returns a sequence that contains the elements of seq (which must be single-valued), but only until the element (inclusive) for which applying pred to the element produces #t, after which the sequence ends.

> procedure (make-do-sequence thunk) → sequence?
> | thunk |  | : |  |
> (or/c (-> (values (any/c . -> . any)
> (any/c . -> . any/c)
> any/c
> (or/c (any/c . -> . any/c) #f)
> (or/c (any/c ... . -> . any/c) #f)
> (or/c (any/c any/c ... . -> . any/c) #f)))
> (-> (values (any/c . -> . any)
> (or/c (any/c . -> . any/c) #f)
> (any/c . -> . any/c)
> any/c
> (or/c (any/c . -> . any/c) #f)
> (or/c (any/c ... . -> . any/c) #f)
> (or/c (any/c any/c ... . -> . any/c) #f))))

Returns a sequence whose elements are generated according to thunk.

The sequence is initiated when thunk is called. The initiated sequence is defined in terms of a position, which is initialized to init-pos, and the element, which may consist of multiple values.

The thunk procedure must return either six or seven values. However, use initiate-sequence to return these multiple values, as opposed to listing the values directly.

If thunk returns six values:

- 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 a init-pos value, which is the initial position.

- The fourth result is a continue-with-pos? function that 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). Alternatively, continue-with-pos? can be #f to indicate that the sequence should always include the current value(s). This function is checked on each position before pos->element is used.

- The fifth result is a continue-with-val? function that is like continue-with-pos?, but it takes the current element value(s) as arguments instead of the current position. Alternatively, continue-with-val? can be #f to indicate that the sequence should always include the value(s) at the current position.

- The sixth result is a continue-after-pos+val? procedure that takes both the current position and the current element value(s) and determines whether the sequence ends after the current element is already included in the sequence. Alternatively, continue-after-pos+val? can be #f to indicate that the sequence can always continue after the current value(s).

If thunk returns seven values, the first result is still the pos->element procedure. However, the second result is now an early-next-pos procedure that is described further below. Alternatively, early-next-pos can be #f, which is equivalent to the identity function. Other results’ positions are shifted by one, so the third result is now next-pos, and the fourth result is now init-pos, etc.

The early-next-pos procedure takes the current position and returns an updated position. This updated position is used for next-pos and continue-after-pos+val?, but not with continue-with-pos? (which uses the original current position). The intent of early-next-pos is to support a sequence where the position must be incremented to avoid keeping a value reachable while a loop processes the sequence value, so early-next-pos is applied just after pos->element. The continue-after-pos+val? function needs to be #f to avoid retaining values to supply to that function.

Each of the procedures listed above is called only once per position. Among the procedures continue-with-pos?, continue-with-val?, and continue-after-pos+val?, 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 #f is used in place of the other two functions.

Changed in version 6.7.0.4 of package base: Added support for the optional second result.

> value prop:sequence : struct-type-property?

Associates a procedure to a structure type that takes an instance of the structure and returns a sequence. If v is an instance of a structure type with this property, then (sequence? v) produces #t.

Using a pre-existing sequence:

Examples:

> > (struct my-set (table)
> #:property prop:sequence
> (lambda (s)
> (in-hash-keys (my-set-table s))))
> > (define (make-set . xs)
> (my-set (for/hash ([x (in-list xs)])
> (values x #t))))
> > (for/list ([c (make-set 'celeriac 'carrot 'potato)])
> c)
> '(carrot celeriac potato)

Using make-do-sequence:

Examples:

> > (require racket/sequence)
> > (struct train (car next)
> #:property prop:sequence
> (lambda (t)
> (make-do-sequence
> (lambda ()
> (initiate-sequence
> #:pos->element train-car
> #:next-pos train-next
> #:init-pos t
> #:continue-with-pos? (lambda (t) t))))))
> > (for/list ([c (train 'engine
> (train 'boxcar
> (train 'caboose
> #f)))])
> c)
> '(engine boxcar caboose)

##### 4.17.1.2`` Sequence Conversion🔗ℹ

> procedure (sequence->stream seq) → stream?
> seq : sequence?

Converts a sequence to a stream, which supports the stream-first and stream-rest operations. Creation of the stream eagerly initiates the sequence, but the stream lazily draws elements from the sequence, caching each element so that stream-first produces the same result each time is applied to a stream.

If extracting an element from seq involves a side-effect, then the effect is performed each time that either stream-first or stream-rest is first used to access or skip an element.

Note that a sequence itself can have state, so multiple calls to sequence->stream on the same seq are not necessarily independent.

Examples:

> > (define inport (open-input-bytes (bytes 1 2 3 4 5)))
> > (define strm (sequence->stream inport))
> > (stream-first strm)
> 1
> > (stream-first (stream-rest strm))
> 2
> > (stream-first strm)
> 1
> > (define strm2 (sequence->stream inport))
> > (stream-first strm2)
> 3
> > (stream-first (stream-rest strm2))
> 4

> > procedure
> > (sequence-generate seq) |  | → |  |
> > (-> boolean?) |  | (-> any)
> seq : sequence?

Initiates a sequence and returns two thunks to extract elements from the sequence. The first returns #t if more values are available for the sequence. The second returns the next element (which may be multiple values) from the sequence; if no more elements are available, the exn:fail:contract exception is raised.

Note that a sequence itself can have state, so multiple calls to sequence-generate on the same seq are not necessarily independent.

Examples:

> > (define inport (open-input-bytes (bytes 1 2 3 4 5)))
> > (define-values (more? get) (sequence-generate inport))
> > (more?)
> #t
> > (get)
> 1
> > (get)
> 2
> > (define-values (more2? get2) (sequence-generate inport))
> > (list (get2) (get2) (get2))
> '(3 4 5)
> > (more2?)
> #f

> procedure (sequence-generate* seq)
> | → |  |
> (or/c list? #f)
> (-> (values (or/c list? #f) procedure?))
> seq : sequence?

Like sequence-generate, but avoids state (aside from any inherent in the sequence) by returning a list of values for the sequence’s first element—or #f if the sequence is empty—and a thunk to continue with the sequence; the result of the thunk is the same as the result of sequence-generate*, but for the second element of the sequence, and so on. If the thunk is called when the element result is #f (indicating no further values in the sequence), the exn:fail:contract exception is raised.

##### 4.17.1.3`` Additional Sequence Operations🔗ℹ

(require racket/sequence) | package: base

The bindings documented in this section are provided by the racket/sequence and racket libraries, but not racket/base.

> value empty-sequence : sequence?

A sequence with no elements.

> procedure (sequence->list s) → list?
> s : sequence?

Returns a list whose elements are the elements of s, each of which must be a single value. If s is infinite, this function does not terminate.

> procedure (sequence-length s) → exact-nonnegative-integer?
> s : sequence?

Returns the number of elements of s by extracting and discarding all of them. If s is infinite, this function does not terminate.

> procedure (sequence-ref s i) → any
> s : sequence?
> i : exact-nonnegative-integer?

Returns the ith element of s (which may be multiple values).

> procedure (sequence-tail s i) → sequence?
> s : sequence?
> i : exact-nonnegative-integer?

Returns a sequence equivalent to s, except that the first i elements are omitted.

In case initiating s involves a side effect, the sequence s is not initiated until the resulting sequence is initiated, at which point the first i elements are extracted from the sequence.

> procedure (sequence-append s ...) → sequence?
> s : sequence?

Returns a sequence that contains all elements of each sequence in the order they appear in the original sequences. The new sequence is constructed lazily.

If all given ss are streams, the result is also a stream.

> procedure (sequence-map f s) → sequence?
> f : procedure?
> s : sequence?

Returns a sequence that contains f applied to each element of s. The new sequence is constructed lazily.

If s is a stream, then the result is also a stream.

> procedure (sequence-andmap f s) → boolean?
> f : (-> any/c ... boolean?)
> s : sequence?

Returns #t if f returns a true result on every element of s. If s is infinite and f never returns a false result, this function does not terminate.

> procedure (sequence-ormap f s) → boolean?
> f : (-> any/c ... boolean?)
> s : sequence?

Returns #t if f returns a true result on some element of s. If s is infinite and f never returns a true result, this function does not terminate.

> procedure (sequence-for-each f s) → void?
> f : (-> any/c ... any)
> s : sequence?

Applies f to each element of s. If s is infinite, this function does not terminate.

> procedure (sequence-fold f i s) → any/c
> f : (-> any/c any/c ... any/c)
> i : any/c
> s : sequence?

Folds f over each element of s with i as the initial accumulator. If s is infinite, this function does not terminate. The f function takes the accumulator as its first argument and the next sequence element as its second.

> procedure (sequence-count f s) → exact-nonnegative-integer?
> f : procedure?
> s : sequence?

Returns the number of elements in s for which f returns a true result. If s is infinite, this function does not terminate.

> procedure (sequence-filter f s) → sequence?
> f : (-> any/c ... boolean?)
> s : sequence?

Returns a sequence whose elements are the elements of s for which f returns a true result. Although the new sequence is constructed lazily, if s has an infinite number of elements where f returns a false result in between two elements where f returns a true result, then operations on this sequence will not terminate during the infinite sub-sequence.

If s is a stream, then the result is also a stream.

> procedure (sequence-add-between s e) → sequence?
> s : sequence?
> e : any/c

Returns a sequence whose elements are the elements of s, but with e between each pair of elements in s. The new sequence is constructed lazily.

If s is a stream, then the result is also a stream.

Examples:

> > (let* ([all-reds (in-cycle '("red"))]
> [red-and-blues (sequence-add-between all-reds "blue")])
> (for/list ([n (in-range 10)]
> [elt red-and-blues])
> elt))
> '("red" "blue" "red" "blue" "red" "blue" "red" "blue" "red" "blue")
> > (for ([text (sequence-add-between '("veni" "vidi" "duci") ", ")])
> (display text))
> veni, vidi, duci

> > procedure
> > (sequence/c | [ | #:min-count min-count] |  |  |  |
> > |  | elem/c ...) |  | → |  | contract?
> min-count : (or/c #f exact-nonnegative-integer?) = #f
> elem/c : contract?

Wraps a sequence, obligating it to produce elements with as many values as there are elem/c contracts, and obligating each value to satisfy the corresponding elem/c. The result is not guaranteed to be the same kind of sequence as the original value; for instance, a wrapped list is not guaranteed to satisfy list?.

If min-count is a number, the stream is required to have at least that many elements in it.

Examples:

> > (define/contract predicates
> (sequence/c (-> any/c boolean?))
> (in-list (list integer?
> string->symbol)))
> > (for ([P predicates])
> (printf "~s\n" (P "cat")))
> #f
> predicates: broke its own contract
> promised: boolean?
> produced: 'cat
> in: an element of
> (sequence/c (-> any/c boolean?))
> contract from: (definition predicates)
> blaming: (definition predicates)
> (assuming the contract is correct)
> at: eval:55:0
> > (define/contract numbers&strings
> (sequence/c number? string?)
> (in-dict (list (cons 1 "one")
> (cons 2 "two")
> (cons 3 'three))))
> > (for ([(N S) numbers&strings])
> (printf "~s: ~a\n" N S))
> 1: one
> 2: two
> numbers&strings: broke its own contract
> promised: string?
> produced: 'three
> in: an element of
> (sequence/c number? string?)
> contract from: (definition numbers&strings)
> blaming: (definition numbers&strings)
> (assuming the contract is correct)
> at: eval:57:0
> > (define/contract a-sequence
> (sequence/c #:min-count 2 char?)
> "x")
> > (for ([x a-sequence]
> [i (in-naturals)])
> (printf "~a is ~a\n" i x))
> 0 is x
> a-sequence: broke its own contract
> promised: a sequence that contains at least 2 values
> produced: "x"
> in: (sequence/c #:min-count 2 char?)
> contract from: (definition a-sequence)
> blaming: (definition a-sequence)
> (assuming the contract is correct)
> at: eval:59:0

##### 4.17.1.3.1`` Additional Sequence Constructors and Functions🔗ℹ

> procedure (in-syntax stx) → sequence?
> stx : syntax?

Produces a sequence whose elements are the successive subparts of stx. Equivalent to (stx->list lst).
An in-syntax application can provide better performance for syntax iteration when it appears directly in a for clause.

Example:

> > (for/list ([x (in-syntax #'(1 2 3))])
> x)
> '(#<syntax:eval:61:0 1> #<syntax:eval:61:0 2> #<syntax:eval:61:0 3>)

Added in version 6.3 of package base.

> procedure (in-slice length seq) → sequence?
> length : exact-positive-integer?
> seq : sequence?

Returns a sequence whose elements are lists with the first length elements of seq, then the next length and so on.

Example:

> > (for/list ([e (in-slice 3 (in-range 8))]) e)
> '((0 1 2) (3 4 5) (6 7))

Added in version 6.3 of package base.

> > procedure
> > (initiate-sequence |
> > |  | #:pos->element pos->element |
> > | [ | #:early-next-pos early-next-pos] |
> > |  | #:next-pos next-pos |
> > |  | #:init-pos init-pos |
> > | [ | #:continue-with-pos? continue-with-pos? |
> > |  | #:continue-with-val? continue-with-val? |
> > |  | #:continue-after-pos+val? continue-after-pos+val?]) |
> | → |  |
> (any/c . -> . any)
> (or/c (any/c . -> . any) #f)
> (any/c . -> . any/c)
> any/c
> (or/c (any/c . -> . any/c) #f)
> (or/c (any/c ... . -> . any/c) #f)
> (or/c (any/c any/c ... . -> . any/c) #f)
> pos->element : (any/c . -> . any)
> early-next-pos : (or/c (any/c . -> . any) #f) = #f
> next-pos : (any/c . -> . any/c)
> init-pos : any/c
> continue-with-pos? : (or/c (any/c . -> . any/c) #f) = #f
> continue-with-val? : (or/c (any/c ... . -> . any/c) #f) = #f
> | continue-after-pos+val? |  | : |  | (or/c (any/c any/c ... . -> . any/c) #f)
> |  |  | = |  | #f

Returns values suitable for the thunk argument in make-do-sequence. See make-do-sequence for the meaning of each argument.

Examples:

> > (define (in-alt-list xs)
> (make-do-sequence
> (λ ()
> (initiate-sequence
> #:pos->element car
> #:next-pos (λ (xs) (cdr (cdr xs)))
> #:init-pos xs
> #:continue-with-pos? pair?
> #:continue-after-pos+val? (λ (xs _) (pair? (cdr xs)))))))
> > (sequence->list (in-alt-list '(1 2 3 4 5 6)))
> '(1 3 5)
> > (sequence->list (in-alt-list '(1 2 3 4 5 6 7)))
> '(1 3 5 7)

Added in version 8.10.0.5 of package base.

top contents ← prev up next →