On this page:
3.1 Generic Collections and Sequences
3.1.1 Collections
gen:  collection
collection?
3.1.1.1 Generic Methods
conj
extend
3.1.1.2 Derived Functions
conj*
extend*
3.1.2 Sequences
gen:  sequence
sequence?
3.1.2.1 Generic Methods
empty?
first
rest
nth
set-nth
update-nth
set-nth*
update-nth*
reverse
sequence->collection
random-access?
3.1.2.2 Derived Functions
last
apply
append
append*
build-sequence
repeat
cycle
naturals
range
randoms
take
drop
subsequence
subsequence*
filter
map
foldl
foldl/  steps
for-each
andmap
ormap
find-best
find-min
find-max
index-of
index-where
remove-first
remove-all
flatten
indexed
chunk
chunk*
append-map
cartesian-product
second
third
fourth
fifth
sixth
seventh
eighth
ninth
tenth
in
for/  sequence
for*/  sequence
for/  sequence/  derived
for*/  sequence/  derived
sequence->list
sequence->list*
sequence->string
sequence->bytes
generate-sequence
3.2 General-Purpose Interfaces
3.2.1 Countable Collections
gen:  countable
countable?
length
known-finite?
3.2.2 Indexable Collections
gen:  indexable
indexable?
ref
set-ref
3.2.3 Using sequences with match
sequence
3.2.4 Contracts on Collections
sequenceof
8.12

3 API Documentation🔗ℹ

3.1 Generic Collections and Sequences🔗ℹ

Generic sequences are the bulk of this library, providing a uniform interface for interacting with collections. Sequences are distinct from Racket sequences, which are a different, much more ad-hoc concept.

A generic collection is any structure that can contain values, while a generic sequence represents a sequence of ordered values.

3.1.1 Collections🔗ℹ

A generic interface that represents any structure that can contain values. The gen:collection interface only provides two functions, conj and extend.

The following built-in datatypes have implementations for gen:collection:

Examples:
> (conj #(1 2 3) 4)

'#(1 2 3 4)

> (extend '() (hash 'a "b" 'c "d"))

'((a . "b") (c . "d"))

procedure

(collection? v)  boolean?

  v : any/c
A predicate that determines if v is a generic collection.

3.1.1.1 Generic Methods🔗ℹ

procedure

(conj coll item)  collection?

  coll : collection?
  item : any/c
Returns a new collection with all the items in coll, plus item. There is no requirement for where the value is added to the collection—lists prepend elements a la cons, while vectors append them.

If extend is implemented but not conj, an implementation will automatically be provided.

Examples:
> (conj '() 'a)

'(a)

> (conj '(1 2) 3)

'(3 1 2)

> (conj #(1 2) 3)

'#(1 2 3)

> (conj (hash) '(a . b))

'#hash((a . b))

procedure

(extend a b)  collection?

  a : collection?
  b : sequence?
Returns a new collection with all the items in both a and b, and the result is the same kind of collection as a.

If conj is implemented but not extend, an implementation will automatically be provided.

Examples:
> (extend '(1 2) '(3 4))

'(4 3 1 2)

> (extend '() #(1 2 3 4))

'(4 3 2 1)

> (extend #() '(1 2 3 4))

'#(1 2 3 4)

> (extend (hash) (set '(a . b) '(b . c)))

'#hash((a . b) (b . c))

3.1.1.2 Derived Functions🔗ℹ

procedure

(conj* coll item ...)  collection?

  coll : collection?
  item : any/c
Repeatedly calls conj for each item provided, in order.

Example:
> (conj* '() 1 2 3 4)

'(4 3 2 1)

procedure

(extend* base extension ...)  collection?

  base : collection?
  extension : sequence?
Repeatedly calls extend for each extension provided, in order.

Example:
> (extend* '() #(1 2) (stream 3 4) (set 5 6))

'(6 5 4 3 2 1)

3.1.2 Sequences🔗ℹ

A generic interface that represents any ordered sequence of values. The gen:sequence interface provides the empty?, first, rest, nth, set-nth, update-nth, reverse, and random-access? functions.

The following built-in datatypes have implementations for gen:sequence:

Example:
> (extend (set) (map + '(1 2 3) #(4 5 6)))

(set 5 7 9)

procedure

(sequence? v)  boolean?

  v : any/c
A predicate that determines if v is a generic sequence.

3.1.2.1 Generic Methods🔗ℹ

procedure

(empty? seq)  boolean?

  seq : sequence?
Determines if seq has no values.

All implementations of gen:sequence are required to implement this method, unless they also implement gen:countable.

Examples:
> (empty? '())

#t

> (empty? (stream))

#t

> (empty? #())

#t

> (empty? '(a b c))

#f

procedure

(first seq)  any/c

  seq : (and/c sequence? (not/c empty?))
Retrieves the first values in seq.

This method is optional if an implementation of nth is provided.

Examples:
> (first '(1 2 3))

1

> (first (set 'a 'b 'c))

'c

> (first (hash 'a 'b 'c 'd))

'(c . d)

procedure

(rest seq)  any/c

  seq : (and/c sequence? (not/c empty?))
Retrieves a new sequence which represents all but the first value in seq.

All implementations of gen:sequence are required to implement this method.

Examples:
> (rest '(1 2 3))

'(2 3)

> (rest (set 'a 'b 'c))

(set 'b 'a)

> (rest (hash 'a 'b 'c 'd))

#<stream>

> (extend (hash) (rest (hash 'a 'b 'c 'd)))

'#hash((a . b))

procedure

(nth seq index)  any/c

  seq : sequence?
  index : exact-nonnegative-integer?
Retrieves the element within seq at index.

If seq also implements gen:countable and is known-finite?, bounds checking will automatically be provided, and a exn:fail:contract error will be raised if index is out of range.

This method is optional if an implementation of first is provided.

Examples:
> (nth '(1 2 3) 1)

2

> (nth #(1 2 3) 2)

3

procedure

(set-nth seq index value)  sequence?

  seq : sequence?
  index : exact-nonnegative-integer?
  value : any/c
Performs a functional update and returns a new sequence with the same elements as seq, except the element at index is replaced with value.

Example:
> (set-nth '(1 2 3) 1 'b)

'(1 b 3)

procedure

(update-nth seq index proc)  sequence?

  seq : sequence?
  index : exact-nonnegative-integer?
  proc : (any/c . -> . any/c)
Like set-nth, but instead of supplying the value to be replaced directly, the proc procedure is applied to the old value at index to produce its replacement.

Example:
> (update-nth '(1 2 3) 1 (λ (n) (+ 10 n)))

'(1 12 3)

procedure

(set-nth* seq index value ... ...)  sequence?

  seq : sequence?
  index : exact-nonnegative-integer?
  value : any/c
Repeatedly calls set-nth using each pair of index and value arguments to produce a final sequence. The set-nth* function must be provided an odd number of arguments (including the seq argument) or a contract error will be raised.

Example:
> (set-nth* '(1 2 3) 0 'a 2 'c)

'(a 2 c)

procedure

(update-nth* seq index proc ... ...)  sequence?

  seq : sequence?
  index : exact-nonnegative-integer?
  proc : (any/c . -> . any/c)
Repeatedly calls update-nth using each pair of index and proc arguments to produce a final sequence. The update-nth* function must be provided an odd number of arguments (including the seq argument) or a contract error will be raised.

Example:
> (update-nth* '(1 2 3) 0 add1 2 sub1)

'(2 2 2)

procedure

(reverse seq)  sequence?

  seq : sequence?
Returns a new sequence with all the elements of seq, but in reverse order. If seq is infinite, this may not terminate.

A default implementation is provided for this method for many built-in sequences, as well as for any custom sequence that is random-access?.

Examples:
> (reverse '(1 2 3))

'(3 2 1)

> (reverse #(1 2 3))

#<random-access-sequence>

> (extend #() (reverse #(1 2 3)))

'#(3 2 1)

procedure

(sequence->collection seq)  collection?

  seq : sequence?
Converts seq to a collection. By default, if seq is already a collection, then this is a no-op, and the result is seq. Otherwise, a collection will be returned that is implemented in terms of append.

Beware that the fallback collection returned by this function can be very slow if repeatedly conj’d upon. However, since most sequences are also collections, it can also be much, much faster than copying the sequence into a collection type with extend. Therefore, it is recommended that general-purpose sequences which are not collections always implement a performant version of sequence->collection.

Examples:
> (reverse #(2 1))

#<random-access-sequence>

> (collection? (reverse #(2 1)))

#f

> (sequence->collection (reverse #(2 1)))

#<appending-collection>

> (sequence->list (conj (sequence->collection (reverse #(2 1))) 3))

'(1 2 3)

procedure

(random-access? seq)  boolean?

  seq : sequence?
Provides a way for sequence implementations to convey whether or not they are random access. If no implementation is provided, the default implementation always returns #f.

This can be used as a heuristic to determine what sort of algorithm to use when operating over generic sequences. For example, if a sequence is determined to be random access, the default implementation for update-nth will use nth and set-nth. Otherwise, it will lazily loop.

3.1.2.2 Derived Functions🔗ℹ

procedure

(last seq)  any/c

  seq : sequence?
Gets the last element of seq. If seq is infinite, this may not terminate.

Examples:
> (last '(1 2 3))

3

> (last (set 'a 'b 'c))

'a

> (last (hash 'a 'b 'c 'd))

'(a . b)

procedure

(apply proc arg ... args #:<kw> kw-arg ...)  any

  proc : procedure?
  arg : any/c
  args : sequence?
  kw-arg : any/c
The same as base:apply but with support for any sequence as the final argument instead of only lists. Just like in base:apply, #:<kw> stands for any keyword.

Examples:
> (apply + #(1 1 1))

3

> (apply + (set 1 1 1))

1

> (apply string-replace #:all? #f "foo" #("o" "a"))

"fao"

procedure

(append seq ...)  sequence?

  seq : sequence?
Returns a new lazy sequence with all the values of the seq arguments concatenated, in order.

In many cases, it may be preferably to use extend or extend*, which may also provide better performance, especially for homogenous sequence types.

Examples:
> (append '(1 2) '(3 4))

#<stream>

> (sequence->list (append '(1 2) '(3 4)))

'(1 2 3 4)

> (sequence->list (append (hash 'a 'b) (set 'c 'd)))

'((a . b) c d)

procedure

(append* seq ... seqs)  sequence?

  seq : sequence?
  seqs : (sequenceof sequence?)
Functionally identical to (apply append seq ... seqs) except that using append* can potentially be lazier since the seqs sequence does not need to be forced. Consequently, append* can concatenate an infinite number of sequences if seqs is an infinite lazy sequence, but append cannot.

Examples:
> (append* (stream '(1 2) '(3 4)))

#<stream>

> (sequence->list (append* (stream '(1 2) '(3 4))))

'(1 2 3 4)

> (sequence->list (append* (stream (hash 'a 'b) (set 'c 'd))))

'((a . b) c d)

procedure

(build-sequence proc)  sequence?

  proc : (exact-nonnegative-integer? . -> . any/c)
(build-sequence n proc)  sequence?
  n : exact-nonnegative-integer?
  proc : (exact-nonnegative-integer? . -> . any/c)
Lazily constructs a sequence where each value is produced by calling proc with the index of the element to be produced. That is, build-sequence creates a sequence, seq, such that (nth seq i) is equal to (proc i) for all valid values of i.

By default, build-sequence produces an infinite sequence. If n is provided, then the result is limited to n elements; it is equivalent to (take n (build-sequence proc)).

Examples:
> (sequence->list (build-sequence 5 values))

'(0 1 2 3 4)

> (sequence->list (subsequence (build-sequence sqr) 5 10))

'(25 36 49 64 81)

procedure

(repeat val)  sequence?

  val : any/c
Creates an infinite sequence simply containing val repeated infinitely.

Examples:
> (repeat 0)

#<repeated-sequence:0>

> (extend #() (take 5 (repeat 0)))

'#(0 0 0 0 0)

procedure

(cycle seq)  sequence?

  seq : (and/c sequence? (not/c empty?))
Creates an infinite sequence containing the values in seq repeated infinitely.

Examples:
> (nth (cycle '(1 2 3)) 10)

2

> (sequence->list (take 5 (cycle '(a b))))

'(a b a b a)

procedure

(naturals [start])  stream?

  start : exact-nonnegative-integer? = 0
The same binding as in-naturals but provided under a different name.

Examples:
> (nth (naturals) 20)

20

> (nth (naturals 5) 20)

25

procedure

(range end)  stream?

  end : number?
(range start end [step])  stream?
  start : number?
  end : number?
  step : number? = 1
The same binding as in-range but provided under a different name.

Examples:
> (nth (range 100) 20)

20

> (nth (range 0 100 0.5) 20)

10.0

procedure

(randoms [rand-gen])

  (sequenceof (and/c real? inexact? (>/c 0) (</c 1)))
  rand-gen : pseudo-random-generator?
   = (make-pseudo-random-generator)
(randoms k [rand-gen])  (sequenceof exact-nonnegative-integer?)
  k : (integer-in 1 4294967087)
  rand-gen : pseudo-random-generator?
   = (make-pseudo-random-generator)
Creates an infinite sequence composed of random values produced via calls to random using rand-gen as the random number generator. Unlike random, randoms does not use current-pseudo-random-generator if rand-gen is not provided. Instead, it will create a new, self-contained generator.

Examples:
> (sequence->list (take 10 (randoms)))

'(0.14065712300517635

  0.09772076279062747

  0.47545191061077585

  0.46739036105973536

  0.7411706245419314

  0.676680984848562

  0.02295888373056609

  0.4272546791166471

  0.04646968996750552

  0.4136459755334917)

> (sequence->list (take 10 (randoms 20)))

'(16 6 10 16 14 5 7 2 3 16)

procedure

(take n seq)  sequence?

  n : exact-nonnegative-integer?
  seq : sequence?
Returns a new lazy sequence that contains the first n elements of seq.

Example:
> (sequence->list (take 10 (in-naturals)))

'(0 1 2 3 4 5 6 7 8 9)

procedure

(drop n seq)  sequence?

  n : exact-nonnegative-integer?
  seq : sequence?
Returns a new sequence that contains all except the first n elements of seq.

Example:
> (sequence->list (drop 5 (range 10)))

'(5 6 7 8 9)

procedure

(subsequence seq start end)  sequence?

  seq : sequence?
  start : exact-nonnegative-integer?
  end : exact-nonnegative-integer?
Returns a new sequence containing the elements of seq from start, inclusive, to end, exclusive. Equivalent to (take (- end start) (drop start seq)).

Example:
> (sequence->list (subsequence (in-naturals) 10 20))

'(10 11 12 13 14 15 16 17 18 19)

procedure

(subsequence* seq start len)  sequence?

  seq : sequence?
  start : exact-nonnegative-integer?
  len : exact-nonnegative-integer?
Like subsequence, but instead of specifying the end index, len specifies the length of the resulting sequence. Equivalent to (take len (drop start seq)) and (subsequence seq start (+ start len)).

Example:
> (sequence->list (subsequence* (in-naturals) 20 5))

'(20 21 22 23 24)

procedure

(filter pred seq)  sequence?

  pred : (any/c . -> . any/c)
  seq : sequence?
Returns a new lazy sequence containing all the elements of seq for which pred applied to them produces a non-#f value.

Examples:
> (filter odd? '(1 2 3 4 5))

#<stream>

> (sequence->list (filter odd? '(1 2 3 4 5)))

'(1 3 5)

procedure

(map proc seq ...+)  sequence?

  proc : procedure?
  seq : sequence?
Returns a new lazy sequence consisting of the results of applying proc to the elements of the provided seq arguments. The proc procedure must take as many arguments as seq arguments are provided. If more than one seq is provided, they must all be of the same length.

Examples:
> (map add1 '(10 20 30))

#<stream>

> (sequence->list (map add1 '(10 20 30)))

'(11 21 31)

> (sequence->list (map + '(5 10 15) #(3 6 9)))

'(8 16 24)

> (define fibs (stream-cons 1 (stream-cons 1 (map + fibs (rest fibs)))))
> (sequence->list (take 15 fibs))

'(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610)

procedure

(foldl proc init seq ...+)  any/c

  proc : procedure?
  init : any/c
  seq : sequence?
Continually applies proc over the elements in the provided seq arguments, passing the result of each application to the subsequent invokation of proc. The proc procedure must accept n+1 arguments where n is the number of seq arguments provided. If more than one seq is provided, they must all be of the same length.

Unlike base:foldl, the accumulator argument is always provided to proc first, not last.

Examples:
> (foldl cons null (set 1 2 3 4))

'((((() . 1) . 2) . 3) . 4)

> (foldl (λ (a b) (cons b a)) null (set 1 2 3 4))

'(4 3 2 1)

procedure

(foldl/steps proc init seq ...+)  sequence?

  proc : procedure?
  init : any/c
  seq : sequence?
Like foldl, but instead of producing a single result, lazily produces a sequence containing each step of the reduction, starting with init.

Examples:
> (sequence->list (foldl/steps + 0 '(1 3 7)))

'(0 1 4 11)

> (sequence->list (foldl/steps conj #() '(a b c)))

'(#() #(a) #(a b) #(a b c))

> (let ([factorials (foldl/steps * 1 (naturals 1))])
    (nth factorials 6))

720

procedure

(for-each proc seq ...+)  void?

  proc : procedure?
  seq : sequence?
Applies proc over the seq arguments just like map, but does so strictly and does not return a sequence. Instead, it simply returns #<void>.

procedure

(andmap proc seq ...+)  any/c

  proc : procedure?
  seq : sequence?
Like map, applies proc over the seq arguments and collects the results together using and like foldl.

Examples:
> (andmap symbol? '(a 1 c d))

#f

> (andmap symbol? '(a b c d))

#t

> (andmap values '(a b c d))

'd

procedure

(ormap proc seq ...+)  any/c

  proc : procedure?
  seq : sequence?
Like map, applies proc over the seq arguments and collects the results together using or like foldl.

Examples:
> (ormap symbol? '(1 2 3 4))

#f

> (ormap symbol? '(1 a 3 4))

#t

> (ormap values '(#f a #f #f))

'a

procedure

(find-best seq >? [#:key extract-key])  any/c

  seq : (and/c sequence? (not/c empty?))
  >? : (any/c any/c . -> . any/c)
  extract-key : (any/c . -> . any/c) = values
A generalization of find-min and find-max, find-best returns the first element, e, of seq for which (>? (extract-key e) (extract-key v)) is non-#f for all other elements, v, of seq. It is assumed that >? is a well-behaved ordering procedure.

Examples:
> (find-best '("pears" "bananas" "apples") string<?)

"apples"

> (find-best '((3 pears) (1 banana) (2 apples)) string<?
             #:key (compose1 symbol->string second))

'(2 apples)

> (find-best '((2 apples) (5 apples)) string<?
             #:key (compose1 symbol->string second))

'(2 apples)

The functions find-min and find-max are defined in terms of find-best, with < and > as the ordering procedures, respectively.

procedure

(find-min seq [#:key extract-key])  any/c

  seq : (and/c sequence? (not/c empty?))
  extract-key : (any/c . -> . real?) = values
Returns the first element, e, of seq for which (extract-key e) returns the smallest value.

Examples:
> (find-min '((3 pears) (1 banana) (2 apples)) #:key first)

'(1 banana)

> (find-min '((1 banana) (1 orange)) #:key first)

'(1 banana)

procedure

(find-max seq [#:key extract-key])  any/c

  seq : (and/c sequence? (not/c empty?))
  extract-key : (any/c . -> . real?) = values
Returns the first element, e, of seq for which (extract-key e) returns the largest value.

Examples:
> (find-max '((3 pears) (1 banana) (2 apples)) #:key first)

'(3 pears)

> (find-max '((1 banana) (1 orange)) #:key first)

'(1 banana)

procedure

(index-of seq v [is-equal?])  (or/c any/c #f)

  seq : sequence?
  v : any/c
  is-equal? : (any/c any/c . -> . any/c) = equal?
Retrieves the index of the first element x of seq for which (is-equal? x v) is not #f. If no such value exists, this function returns #f.

Examples:
> (index-of '(a b c) 'b)

1

> (index-of '(a b c) 'd)

#f

> (index-of '(1 2 3) 2.0)

#f

> (index-of '(1 2 3) 2.0 =)

1

procedure

(index-where seq proc)  (or/c any/c #f)

  seq : sequence?
  proc : (any/c . -> . any/c)
Retrieves the index of the first element x of seq for which (proc x) is not #f. If no such value exists, this function returns #f.

Examples:
> (index-where '(1 2 3) positive?)

0

> (index-where '(-1 2 3) positive?)

1

> (index-where '(-1 -2 -3) positive?)

#f

procedure

(remove-first seq val [=?])  sequence?

  seq : sequence?
  val : any/c
  =? : (any/c any/c . -> . any/c) = equal?
(remove-first seq val =? failure-thunk)  any/c
  seq : sequence?
  val : any/c
  =? : (any/c any/c . -> . any/c)
  failure-thunk : (-> any/c)
Returns a new sequence like seq, but with the first ocurrence of an element equal to val omitted, as determined by =?. By default, if no such element exists, seq is returned unmodified. Alternatively, a failure-thunk may be provided, which will be invoked if no equal element exists to produce a return value.

Importantly, if no failure-thunk is provided, remove-first will be lazy in its production of a new sequence. However, if failure-thunk is provided, remove-first will be strict. This is necessary because the result may not be a sequence, and a non-sequence value must be returned strictly in ordinary Racket.

Examples:
> (sequence->list (remove-first '(a b c a b c) 'a))

'(b c a b c)

> (sequence->list (remove-first '(1 2 3 1 2 3) 1.0))

'(1 2 3 1 2 3)

> (sequence->list (remove-first '(1 2 3 1 2 3) 1.0 =))

'(2 3 1 2 3)

> (remove-first '(1 2 3 1 2 3) 1.0 equal? (thunk #f))

#f

procedure

(remove-all seq val [=?])  sequence?

  seq : sequence?
  val : any/c
  =? : (any/c any/c . -> . any/c) = equal?
Lazily produces a new sequence like seq, but with all elements equal to val omitted, as determined by =?.

Examples:
> (sequence->list (remove-all '(a b c a b c) 'a))

'(b c b c)

> (sequence->list (remove-all '(1 2 3 1 2 3) 1.0))

'(1 2 3 1 2 3)

> (sequence->list (remove-all '(1 2 3 1 2 3) 1.0 =))

'(2 3 2 3)

procedure

(flatten s)  sequence?

  s : sequence?
Flattens a potentially nested sequence into a sequence of flat values.

Examples:
> (flatten '((a) b (c (d) e) ()))

#<stream>

> (sequence->list (flatten '((a) b (c (d) e) ())))

'(a b c d e)

> (sequence->list (flatten '((((()()()))(((()))())))))

'()

> (sixth (flatten (repeat 1)))

1

procedure

(indexed seq)

  (sequenceof (cons/c exact-nonnegative-integer? any/c))
  seq : sequence?
Lazily produces a new sequence based on seq, but each element is paired with its index within the sequence.

Examples:
> (sequence->list (indexed '(a b c)))

'((0 . a) (1 . b) (2 . c))

> (extend (hash) (indexed '(a b c)))

'#hash((0 . a) (1 . b) (2 . c))

procedure

(chunk n seq)  (sequenceof sequence?)

  n : exact-positive-integer?
  seq : sequence?
Lazily produces a new sequence based on seq but with its elements grouped into subsequences taken n at a time. If the length of seq is not evenly divisible by n, then the final subsequence will contain the remaining elements.

Example:
> (sequence->list* (chunk 3 (range 10)))

'((0 1 2) (3 4 5) (6 7 8) (9))

procedure

(chunk* n seq)  (sequenceof sequence?)

  n : exact-positive-integer?
  seq : sequence?
Like chunk, but if the length of seq is not evenly divisible by n, then an exception will be raised.

Example:
> (sequence->list* (chunk* 3 (range 10)))

rest: contract violation

  expected: (not/c empty?)

  given: #<stream>

  in: an and/c case of

      the 1st argument of

      (-> (and/c sequence? (not/c empty?)) any)

  contract from:

      <pkgs>/collections-lib/data/collection/collection.rkt

  blaming:

<pkgs>/collections-lib/data/collection/sequence.rkt

   (assuming the contract is correct)

  at:

<pkgs>/collections-lib/data/collection/collection.rkt:34:3

procedure

(append-map f seq ...+)  sequence?

  f : procedure?
  seq : sequence?
Like (apply append (map f seq ...)).

Example:
> (sequence->list (append-map values '((1) (2) (3))))

'(1 2 3)

procedure

(cartesian-product seq ...)  (sequenceof sequence?)

  seq : sequence?
Computes the n-ary Cartesian product of the given sequences. The result is computed lazily—if any of the seqs are infinite, then the result will also be infinite.

Examples:
> (sequence->list* (cartesian-product '(1 2) '(a b) '(c d)))

'((1 a c) (1 a d) (1 b c) (1 b d) (2 a c) (2 a d) (2 b c) (2 b d))

> (sequence->list* (cartesian-product '(a) '(1 2 3)))

'((a 1) (a 2) (a 3))

> (sequence->list* (cartesian-product '(4 5 6) '(d e f) '(#t #f)))

'((4 d #t)

  (4 d #f)

  (4 e #t)

  (4 e #f)

  (4 f #t)

  (4 f #f)

  (5 d #t)

  (5 d #f)

  (5 e #t)

  (5 e #f)

  (5 f #t)

  (5 f #f)

  (6 d #t)

  (6 d #f)

  (6 e #t)

  (6 e #f)

  (6 f #t)

  (6 f #f))

procedure

(second seq)  any/c

  seq : sequence?

procedure

(third seq)  any/c

  seq : sequence?

procedure

(fourth seq)  any/c

  seq : sequence?

procedure

(fifth seq)  any/c

  seq : sequence?

procedure

(sixth seq)  any/c

  seq : sequence?

procedure

(seventh seq)  any/c

  seq : sequence?

procedure

(eighth seq)  any/c

  seq : sequence?

procedure

(ninth seq)  any/c

  seq : sequence?

procedure

(tenth seq)  any/c

  seq : sequence?
A set of helper functions for accessing elements of seq implemented in terms of nth. A random-access implementation of nth will make these random-access as well.

Examples:

procedure

(in seq)  stream?

  seq : sequence?
When used as a procedure, converts seq into a lazy stream. This function is primarily intended to be used directly in a for clause, in which case the sequence will be iterated directly without any conversion taking place.

Examples:
> (in '(1 2 3 4))

#<stream>

> (for ([e (in (filter even? (set 1 2 3 4 5 6)))])
    (displayln e))

2

4

6

syntax

(for/sequence (for-clause ...) body-or-break ... body)

syntax

(for*/sequence (for-clause ...) body-or-break ... body)

Both forms iterate like for, but the results of the body expressions are collected into a lazy sequence. This means that the body of the loop isn’t actually evaluated until the sequence is used, so any side-effects performed will be delayed until the sequence is forced.

The for*/sequence form is the same as for/sequence but with the implicit nesting behavior of for*.

Example:
> (extend
   (set)
   (for/sequence ([i (in-range 10)])
     (* i i)))

(set 0 16 64 1 49 81 4 36 9 25)

syntax

(for/sequence/derived name-id (for-clause ...) body-or-break ... body)

syntax

(for*/sequence/derived name-id (for-clause ...) body-or-break ... body)

Both forms work exactly like for/sequence or for*/sequence, respectively, except that errors are reported in terms of name-id. This can be useful for creating new forms that collect the results of for/sequence.

Examples:
> (define-syntax-rule (for/immutable-vector . rest)
    (extend #() (for/sequence/derived for/immutable-vector . rest)))
> (for/immutable-vector ([i (in-range 10)])
    (* i i))

'#(0 1 4 9 16 25 36 49 64 81)

> (for/immutable-vector (malformed)
    (* i i))

eval:3:0: for/immutable-vector: bad sequence binding clause

  at: malformed

  in: (for/immutable-vector (malformed) (* i i))

procedure

(sequence->list seq)  list?

  seq : sequence?
Converts any sequence to a list. Equivalent to (reverse (extend '() seq)).

If seq is infinite, then this function will not terminate, and it will infinitely allocate memory until it is exhausted.

Examples:
> (sequence->list #(1 2 3))

'(1 2 3)

> (sequence->list (hash 'a 'b 1 2 "foo" "bar"))

'((1 . 2) (a . b) ("foo" . "bar"))

procedure

(sequence->list* seq)  list?

  seq : sequence?
Like sequence->list, but recursively calls itself on any of the elements of seq that are also sequences.

If seq or any of its subsequences are infinite, then this function will not terminate, and it will infinitely allocate memory until it is exhausted.

Examples:
> (sequence->list* #(1 #(2 3)))

'(1 (2 3))

> (sequence->list* (chunk 2 (range 10)))

'((0 1) (2 3) (4 5) (6 7) (8 9))

procedure

(sequence->string seq)  (and/c string? sequence?)

  seq : (sequenceof char?)
Converts seq, which must contain only characters, to an immutable string.

procedure

(sequence->bytes seq)  (and/c bytes? sequence?)

  seq : (sequenceof byte?)
Converts seq, which must contain only bytes, to an immutable byte string.

procedure

(generate-sequence gen)  sequence?

  gen : generator?
Creates a new lazy sequence by repeatedly calling gen until generator-state returns 'done. The first element of the sequence is evaluated eagerly, but the remaining sequence is lazy.

Example:
> (sequence->list
   (take 5 (generate-sequence (generator ()
                                (let loop ([n 0])
                                  (yield (* n n))
                                  (loop (add1 (* n n))))))))

'(0 1 4 25 676)

3.2 General-Purpose Interfaces🔗ℹ

3.2.1 Countable Collections🔗ℹ

Lots of data structures may be considered countable—that is, they have a discrete number of elements. The gen:countable interface only provides a single function, length.

A generic interface that defines two functions, length, which accepts a single argument and returns the number of elements contained within the collection, and known-finite?, which provides a pessimistic check for finite collections.

The following built-in datatypes have implementations for gen:countable:

For streams, if the argument is infinite, then length does not terminate.

Examples:
> (length (range 20))

20

> (length #(λ))

1

> (length "Hello!")

6

> (length (set 1 2 3 4 5))

5

> (struct wrapped-collection (value)
    #:methods gen:countable
    [(define/generic -length length)
     (define (length w)
       (-length (wrapped-collection-value w)))])
> (length (wrapped-collection (hash 'a "b" 'c "d")))

2

procedure

(countable? v)  boolean?

  v : any/c
A predicate that identifies if v is countable.

procedure

(length countable)  exact-nonnegative-integer?

  countable : countable?
Returns the number of discrete elements contained by countable. If countable is infinite, then this function does not terminate.

procedure

(known-finite? countable)  boolean?

  countable : countable?
If this function returns #t, then countable must be finite, and therefore, length must terminate. If this function returns #f, then no additional information is gained: countable could be either finite or infinite.

If no implementation for known-finite? is provided, it will always return #f.

Examples:
> (known-finite? #(a b c))

#t

> (known-finite? (sequence->list (range 10)))

#t

> (known-finite? (in-naturals))

#f

3.2.2 Indexable Collections🔗ℹ

Data structures are indexable if they provide any sort of indexed data.

A generic interface that defines ref and set-ref for getting and setting key-value data.

Be careful when using ref with generic sequences. If numeric indexing is your intention, use nth instead, since ref and nth may have different behaviors on the same sequence. Notably, ref on association lists uses dict-ref, not list-ref.

All generic sequences are also indexable, so implementations of gen:sequence do not need to implement gen:indexable if they provide simply key/value mappings based on index. Additionally, mutable hash tables, mutable vectors, and dictionaries are also indexable.

Examples:
> (ref '(a b c) 1)

'b

> (ref (hash 'foo "bar") 'foo)

"bar"

> (ref '((1 . 2) (3 . 4)) 1)

2

> (set-ref '(a b c) 1 'x)

'(a x c)

> (set-ref (hash 'foo "bar") 'foo "baz")

'#hash((foo . "baz"))

> (set-ref '((1 . 2) (3 . 4)) 1 -2)

'((1 . -2) (3 . 4))

procedure

(indexable? v)  boolean?

  v : any/c
A predicate that identifies if v is indexable.

procedure

(ref collection index)  any

  collection : indexable?
  index : any/c
Returns the value associated with the provided index for the given collection.

procedure

(set-ref collection index value)  any

  collection : indexable?
  index : any/c
  value : any/c
Returns a new collection with all the associations in collection, plus a association between index and value.

3.2.3 Using sequences with match🔗ℹ

syntax

(sequence svp ...)

 
svp = pat
  | pat ooo
     
ooo = ...
Similar to list patterns for match, but matches any type of sequence and does not support ..k splicing patterns.

If pat ... splicing patterns are used in a non-final position, the sequence will be forced, and if the sequence is not finite, the match will not terminate. Otherwise, the other elements of the sequence not matched will not be forced, including a possible lazy tail.

Examples:
> (match (stream 1 2 3 4)
    [(sequence a b c d) c])

3

> (match (stream 1 2 3 4)
    [(sequence a b ... c) b])

'(2 3)

> (match (stream 1 2 3 4)
    [(sequence a b ...) b])

#<stream>

3.2.4 Contracts on Collections🔗ℹ

procedure

(sequenceof ctc [#:chaperone? chaperone?])  contract?

  ctc : contract?
  chaperone? : any/c = #f
Produces a contract that recognizes sequences and ensures their elements all match the ctc contract. When a sequenceof contract is applied to a sequence, the result is not eq? to its input.

If chaperone? is non-#f, then the result will always be a chaperone-contract?, and ctc must also be a chaperone-contract?. If chaperone? is #f, the result will always be a simple contract?.

For most sequence types, when a sequenceof contract is applied to a sequence, the result is always equal? to its input. However, for a small set of sequences, such as hash tables, strings, and byte strings, the result will be an entirely disparate type of sequence. This behavior is only supported for non-chaperone contracts, so if chaperone? is non-#f, then those sequences will not be permitted by the contract.