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

4.17.1 Sequences🔗

+(part ("(lib scribblings/guide/guide.scrbl)" "sequences")) in (part ("(lib scribblings/guide/guide.scrbl)" "top")) introduces sequences.

sequence 封装了一个有序的值集合。 sequence 的元素可以通过 for 语法形式之一、通过 sequence-generate 返回的过程,或者通过将 sequence 转换为 stream 来提取。

sequence 数据类型与许多其他数据类型重叠。在内置数据类型中,sequence 数据类型包括以下:

一个非负 整数精确数 k 作为一个 sequence, 类似于 (in-range k),但 k 本身不是一个 stream

可以使用结构体类型属性定义自定义 sequences。定义自定义 sequence 最简单的方法是使用 gen:stream 泛型接口。Streams 适用于可直接迭代的数据结构。 例如,列表可以通过 firstrest 直接迭代。另一方面,向量不能直接迭代: 迭代必须通过索引进行。对于不能直接迭代的数据结构,该数据结构的 iterator 可以定义为一个 stream(例如,包含向量索引的结构体)。

例如,展开链表(表示为向量列表)本身不适合 stream 抽象,但具有可以表示为 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)

prop:sequence 属性在指定迭代方面提供了更大的灵活性,例如当需要预处理步骤来准备数据以进行迭代时。 make-do-sequence 函数创建一个 sequence,给定一个返回实现 sequence 的过程的 thunk, 而 prop:sequence 属性可以与结构体类型关联以实现其到 sequence 的隐式转换。

对于大多数 sequence 类型,从 sequence 中提取元素不会对原始 sequence 值产生副作用; 例如,从列表中提取元素的 sequence 不会改变列表。对于其他 sequence 类型, 每次提取都意味着一个副作用;例如,从端口提取字节的 sequence 会导致从端口读取字节。 一个 sequence 的状态可以跨越该 sequence 的所有使用(如端口), 也可以限定在每次通过 for 形式、sequence->streamsequence-generatesequence-generate* initiate 该 sequence 的不同时间。 具体来说,传递给 make-do-sequence 的 thunk 在每次使用该 sequence 时被调用以 initiate 该 sequence。 因此,不同的 sequences 在被多次 initiate 时表现不同。

> (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)

此外,sequence 中的后续元素可能仅仅通过调用 sequence-generate 的第一个结果就被"消耗"了, 即使第二个结果从未被调用。

> (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)

在此示例中,第一次调用 sequence-generate 中嵌入的状态仅仅通过调用 more?.1 就"获取"了 98

sequence 的单个元素通常对应单个值,但一个元素也可能对应多个值。 例如,哈希表为 sequence 中的每个元素生成两个值——一个键及其值。

4.17.1.1 Sequence Predicate and Constructors🔗

procedure

(sequence? v)  boolean?

  v : any/c
如果 v 可以用作 sequence 则返回 #t,否则返回 #f

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
返回一个元素为数字的 sequence(同时也是 stream)。 单参数形式 (in-range end) 等价于 (in-range 0 end 1)。 sequence 中的第一个数字是 start,每个后续元素通过将 step 加到前一个元素来生成。 如果 step 非负,sequence 在元素大于或等于 end 之前停止; 如果 step 为负,sequence 在元素小于或等于 end 之前停止。
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

当给定零作为 step 时,in-range 返回一个无限 sequence。 当 step 是一个非常小的数字,且 step 或 sequence 元素是浮点数时, 它也可能返回无限 sequences。

procedure

(in-inclusive-range start end [step])  stream?

  start : real?
  end : real?
  step : real? = 1
类似于 in-range,但 sequence 的停止条件已更改,使得最后一个元素允许等于 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
返回一个从 start 开始的精确整数的无限 sequence(同时也是 stream), 其中每个元素比前一个元素大一。
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?
返回一个 sequence(同时也是 stream),等价于直接使用 lst 作为 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: 改进了 for 中列表的元素可达性保证。

procedure

(in-mlist mlst)  sequence?

  mlst : mlist?
返回一个等价于 mlst 的 sequence。虽然预期 mlstmutable list, 但 in-mlist 最初只检查 mlst 是否是 mutable pairnull, 因为它可能在迭代期间发生变化。

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
当不提供可选参数时,返回一个等价于 vec 的 sequence。

See Vectors for information on using vectors as sequences.

可选参数 startstopstepin-range 类似, 不同之处在于 stop#f 值等价于 (vector-length vec)。 也就是说,sequence 中的第一个元素是 (vector-ref vec start), 每个后续元素通过将 step 加到前一个元素的索引来生成。 如果 step 非负,sequence 在索引大于或等于 end 之前停止; 如果 step 为负,sequence 在索引小于或等于 end 之前停止。

如果 start 不是有效索引,则 exn:fail:contract exception is raised, 除非 startstop(vector-length vec) 相等, 此时结果为空 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)

如果 stop 不在 [-1, (vector-length vec)] 范围内,则 exn:fail:contract exception is raised。

如果 start 小于 stopstep 为负,则 exn:fail:contract exception is raised。 类似地,如果 start 大于 stopstep 为正,则 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
当不提供可选参数时,返回一个等价于 str 的 sequence。

See Strings for information on using strings as sequences.

可选参数 startstopstepin-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
当不提供可选参数时,返回一个等价于 bstr 的 sequence。

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

可选参数 startstopstepin-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)
返回一个 sequence,其元素通过对 in 调用 r 产生,直到产生 eof

procedure

(in-input-port-bytes in)  sequence?

  in : input-port?
返回一个等价于 (in-port read-byte in) 的 sequence。

procedure

(in-input-port-chars in)  sequence?

  in : input-port?
返回一个元素从 in 读取为字符的 sequence(等价于 (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
返回一个等价于 (in-port (lambda (p) (read-line p mode)) in) 的 sequence。 注意默认模式是 'any,而 read-line 的默认模式是 '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
返回一个等价于 (in-port (lambda (p) (read-bytes-line p mode)) in) 的 sequence。 注意默认模式是 'any,而 read-bytes-line 的默认模式是 'linefeed

procedure

(in-hash hash)  sequence?

  hash : hash?
(in-hash hash bad-index-v)  sequence?
  hash : hash?
  bad-index-v : any/c
返回一个等价于 hash 的 sequence,除非提供了 bad-index-v

如果提供了 bad-index-v,则当 hash 被并发修改使得迭代没有 valid hash index 时, bad-index-v 将同时作为键和值返回。提供 bad-index-v 在遍历具有弱引用键的哈希表时特别有用, 因为条目可以被异步移除(即在 in-hash 已承诺进行另一次迭代之后,但在它能够访问下一次迭代的条目之前)。

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: 添加了可选的 bad-index-v 参数。

procedure

(in-hash-keys hash)  sequence?

  hash : hash?
(in-hash-keys hash bad-index-v)  sequence?
  hash : hash?
  bad-index-v : any/c
返回一个元素为 hash 的键的 sequence,使用 bad-index-v 的方式与 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: 添加了可选的 bad-index-v 参数。

procedure

(in-hash-values hash)  sequence?

  hash : hash?
(in-hash-values hash bad-index-v)  sequence?
  hash : hash?
  bad-index-v : any/c
返回一个元素为 hash 的值的 sequence,使用 bad-index-v 的方式与 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: 添加了可选的 bad-index-v 参数。

procedure

(in-hash-pairs hash)  sequence?

  hash : hash?
(in-hash-pairs hash bad-index-v)  sequence?
  hash : hash?
  bad-index-v : any/c
返回一个元素为 pairs 的 sequence,每个 pair 包含 hash 中的一个键及其值 (与直接使用 hash 作为 sequence 来获取每个元素的键和值作为单独的值不同)。

bad-index-v 参数(如果提供)的使用方式与 in-hash 相同。 当遇到无效索引时,sequence 中的 pair 将以 bad-index-v 作为其 carcdr

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: 添加了可选的 bad-index-v 参数。

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 构造器。 这些可能比类似的 in-hash 形式性能更好。

Added in version 6.4.0.6 of package base.
Changed in version 7.0.0.10: 添加了可选的 bad-index-v 参数。
Changed in version 8.0.0.10: 添加了 ephemeron 变体。

procedure

(in-directory [dir use-dir?])  sequence?

  dir : (or/c #f path-string?) = #f
  use-dir? : ((and/c path? complete-path?) . -> . any/c)
   = (lambda (dir-path) #t)
返回一个产生 dir 内文件、目录和链接的所有路径的 sequence, 但 use-dir? 返回 #f 的目录的内容除外。 如果 dir 不是 #f,则每个产生的路径都以 dir 作为前缀。 如果 dir#f,则产生当前目录中和相对于当前目录的路径。

in-directory sequence 递归遍历嵌套子目录(由 use-dir? 过滤)。 要生成仅包含目录的直接内容的 sequence,请使用 directory-list 的结果作为 sequence。

每个目录的直接内容按 path<? 排序报告,并且子目录的内容在目录中后续路径之前报告。

Examples:
> (current-directory (collection-path "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:main_rkt.dep> #<path:main_rkt.zo>)

> (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:main.rkt> #<path:compiled>)

Changed in version 6.0.0.1 of package base: 添加了 use-dir? 参数。
Changed in version 6.6.0.4: 添加了排序结果的保证。

procedure

(in-producer producer)  sequence?

  producer : procedure?
(in-producer producer stop arg ...)  sequence?
  producer : procedure?
  stop : any/c
  arg : any/c
返回一个包含对 producer 连续调用产生的值的 sequence,producer 通常使用某些状态来完成其工作。

如果未给定 stop 值,sequence 将无限继续,因此通常将其与有限 sequence 一起使用或使用 #:break 等。 如果给定了 stop 值,则用于标识标记 sequence 结束的值(且 stop 值不包含在 sequence 中); stop 可以是应用于 producer 结果的谓词,也可以是与结果用 eq? 测试的值。 (如果停止值本身是一个函数或 producer 返回多个值,则 stop 参数必须是谓词。)

如果指定了额外的 arg,它们会传递给每次对 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
返回一个产生单个值的 sequence:v

此形式主要用于 for*/list 等形式中的 let 类绑定——但更近期添加的 #:do 子句形式覆盖了许多相同的用途。

procedure

(in-indexed seq)  sequence?

  seq : sequence?
返回一个 sequence,其中每个元素有两个值:seq 产生的值,以及从 0 开始的非负精确整数。 seq 的元素必须是单值的。

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?
返回一个由所有输入 sequences 组成的 sequence,一个接一个。 每个 seq 只在前一个 seq 耗尽后才被 initiate。 如果只提供了一个 seq,则返回 seq;否则,每个 seq 的元素必须都具有相同数量的值。

procedure

(in-cycle seq ...)  sequence?

  seq : sequence?
类似于 in-sequences,但 sequences 在无限循环中重复,其中每个 seq 在每次迭代中都被重新 initiate。 注意,如果未提供 seq 或所有 seq 都变为空,则 in-cycle 产生的 sequence 在需要元素时永远不会返回—— 或者如果所有 seq 最初都为空,则在 sequence 被 initiate 时也不会返回。

procedure

(in-parallel seq ...)  sequence?

  seq : sequence?
返回一个 sequence,其中每个元素具有与提供的 seq 数量相同的值; 这些值按顺序是每个 seq 的值。每个 seq 的元素必须是单值的。

procedure

(in-values-sequence seq)  sequence?

  seq : sequence?
返回一个类似于 seq 的 sequence,但它将 seq 每个元素的多个值组合为元素列表。

procedure

(in-values*-sequence seq)  sequence?

  seq : sequence?
返回一个类似于 seq 的 sequence,但当 seq 的元素具有多个值或单个列表值时, 这些值被组合在列表中。换句话说,in-values*-sequence 类似于 in-values-sequence, 不同之处在于非列表的单值元素不会被包装在列表中。

procedure

(stop-before seq pred)  sequence?

  seq : sequence?
  pred : (any/c . -> . any)
返回一个包含 seq 元素的 sequence(必须是单值的), 但仅直到将 pred 应用于元素产生 #t 的最后一个元素为止, 之后 sequence 结束。

procedure

(stop-after seq pred)  sequence?

  seq : sequence?
  pred : (any/c . -> . any)
返回一个包含 seq 元素的 sequence(必须是单值的), 但仅直到将 pred 应用于元素产生 #t 的元素(含), 之后 sequence 结束。

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 (() () #:rest list? . ->* . any/c) #f)
                  (or/c ((any/c) () #:rest list? . ->* . 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 (() () #:rest list? . ->* . any/c) #f)
                  (or/c ((any/c) () #:rest list? . ->* . any/c) #f))))
返回一个 sequence,其元素由 thunk 返回的过程和初始值生成,thunk 被调用以 initiate 该 sequence。 已启动的 sequence 由 position 定义,它被初始化为 thunk 的第三个结果, 以及 element,它可能由多个值组成。

thunk 结果定义生成的元素如下:
  • 第一个结果是 pos->element 过程,它接受当前位置并返回当前元素的值。

  • 可选的第二个结果是 early-next-pos 过程,进一步描述如下。 或者,可选的第二个结果可以是 #f,等价于恒等函数。

  • 第三个(或第二个)结果是 next-pos 过程,它接受当前位置并返回下一个位置。

  • 第四个(或第三个)结果是初始位置。

  • 第五个(或第四个)结果是 continue-with-pos? 函数,它接受当前位置, 如果 sequence 包含当前位置的值则返回真结果,如果 sequence 应该结束而不是包含值则返回假。 或者,第五个(或第四个)结果可以是 #f 表示 sequence 应该始终包含当前值。 此函数在使用 pos->element 之前对每个位置进行检查。

  • 第六个(或第五个)结果是 continue-with-val? 函数,类似于第五个(或第四个)结果, 但它接受当前元素值而不是当前位置。或者,第六个(或第五个)结果可以是 #f 表示 sequence 应该始终包含当前位置的值。

  • 第七个(或第六个)结果是 continue-after-pos+val? 过程, 它同时接受当前位置和当前元素值,并确定在当前元素已包含在 sequence 中后 sequence 是否结束。 或者,第七个(或第六个)结果可以是 #f 表示 sequence 在当前元素后总是可以继续。

early-next-pos 过程(可选的第二个结果)接受当前位置并返回更新后的位置。 此更新后的位置用于 next-poscontinue-after-pos+val?, 但不用于 continue-with-pos?(它使用原始当前位置)。 early-next-pos 的意图是支持一种 sequence,其中位置必须递增以避免在循环处理 sequence 值时 保持值可达,因此 early-next-pospos->element 之后立即应用。

上面列出的每个过程每个位置只调用一次。在最后三个过程中,一旦其中一个过程返回 #f, sequence 就结束,且不再调用任何过程。通常,其中一个函数确定结束条件, 而 #f 用于代替其他两个函数。

Changed in version 6.7.0.4 of package base: 添加了对可选第二个结果的支持。

将一个过程关联到结构体类型,该过程接受结构体的实例并返回一个 sequence。 如果 v 是具有此属性的结构体类型的实例,则 (sequence? v) 产生 #t

使用预先存在的 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)

'(potato celeriac carrot)

使用 make-do-sequence

Examples:
> (struct train (car next)
    #:property prop:sequence
    (lambda (t)
      (make-do-sequence
       (lambda ()
         (values train-car train-next t
                 (lambda (t) t)
                 (lambda (v) #t)
                 (lambda (t v) #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?
将 sequence 转换为 stream,支持 stream-firststream-rest 操作。 创建 stream 会立即 initiate 该 sequence,但 stream 延迟地从 sequence 中提取元素, 缓存每个元素使得 stream-first 每次应用于 stream 时产生相同的结果。

如果从 seq 提取元素涉及副作用,则每次首次使用 stream-firststream-rest 访问或跳过元素时都会执行该副作用。

注意 sequence 本身可以有状态,因此对同一个 seq 的多次 sequence->stream 调用不一定独立。

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?
Initiate 一个 sequence 并返回两个 thunk 以从 sequence 中提取元素。 如果 sequence 有更多可用值,第一个返回 #t。 第二个返回 sequence 的下一个元素(可能是多个值);如果没有更多可用元素, 则 exn:fail:contract exception is raised。

注意 sequence 本身可以有状态,因此对同一个 seq 的多次 sequence-generate 调用不一定独立。

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?
类似于 sequence-generate,但通过返回 sequence 第一个元素的值列表 (如果 sequence 为空则返回 #f)以及继续该 sequence 的 thunk 来避免状态 (除了 sequence 中固有的任何状态);thunk 的结果与 sequence-generate* 的结果相同, 但针对 sequence 的第二个元素,依此类推。如果在元素结果为 #f(表示 sequence 中没有更多值) 时调用 thunk,则 exn:fail:contract exception is raised。

4.17.1.3 Additional Sequence Operations🔗

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

一个没有元素的 sequence。

procedure

(sequence->list s)  list?

  s : sequence?
返回一个列表,其元素是 s 的元素,每个元素必须是单个值。 如果 s 是无限的,此函数不会终止。

通过提取并丢弃所有元素来返回 s 的元素数量。 如果 s 是无限的,此函数不会终止。

procedure

(sequence-ref s i)  any

  s : sequence?
  i : exact-nonnegative-integer?
返回 s 的第 i 个元素(可能是多个值)。

procedure

(sequence-tail s i)  sequence?

  s : sequence?
  i : exact-nonnegative-integer?
返回一个等价于 s 的 sequence,但省略了前 i 个元素。

如果 initiating s 涉及副作用, 则 sequence s 直到结果 sequence 被 initiate 时才被 initiate, 此时前 i 个元素从 sequence 中提取。

procedure

(sequence-append s ...)  sequence?

  s : sequence?
返回一个包含每个 sequence 的所有元素的 sequence,按原始 sequence 中出现的顺序排列。 新的 sequence 是延迟构造的。

如果所有给定的 s 都是 streams,则结果也是一个 stream

procedure

(sequence-map f s)  sequence?

  f : procedure?
  s : sequence?
返回一个包含将 f 应用于 s 每个元素的结果的 sequence。 新的 sequence 是延迟构造的。

如果 sstream,则结果也是一个 stream

procedure

(sequence-andmap f s)  boolean?

  f : (-> any/c ... boolean?)
  s : sequence?
如果 fs 的每个元素都返回真结果,则返回 #t。 如果 s 是无限的且 f 从不返回假结果,此函数不会终止。

procedure

(sequence-ormap f s)  boolean?

  f : (-> any/c ... boolean?)
  s : sequence?
如果 fs 的某个元素返回真结果,则返回 #t。 如果 s 是无限的且 f 从不返回真结果,此函数不会终止。

procedure

(sequence-for-each f s)  void?

  f : (-> any/c ... any)
  s : sequence?
f 应用于 s 的每个元素。如果 s 是无限的,此函数不会终止。

procedure

(sequence-fold f i s)  any/c

  f : (-> any/c any/c ... any/c)
  i : any/c
  s : sequence?
i 作为初始累加器,将 f 折叠到 s 的每个元素上。 如果 s 是无限的,此函数不会终止。f 函数以累加器作为第一个参数, 以下一个 sequence 元素作为第二个参数。

procedure

(sequence-count f s)  exact-nonnegative-integer?

  f : procedure?
  s : sequence?
返回 sf 返回真结果的元素数量。 如果 s 是无限的,此函数不会终止。

procedure

(sequence-filter f s)  sequence?

  f : (-> any/c ... boolean?)
  s : sequence?
返回一个元素为 sf 返回真结果的元素的 sequence。 虽然新的 sequence 是延迟构造的,但如果 s 有无限多个元素, 其中 f 在两个返回真结果的元素之间返回假结果,则对这个 sequence 的操作 在无限子 sequence 期间不会终止。

如果 sstream,则结果也是一个 stream

procedure

(sequence-add-between s e)  sequence?

  s : sequence?
  e : any/c
返回一个元素为 s 的元素的 sequence,但在 s 的每对元素之间插入 e。 新的 sequence 是延迟构造的。

如果 sstream,则结果也是一个 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?
包装一个 sequence,要求它产生与 elem/c contracts 数量相同的值的元素, 并要求每个值满足对应的 elem/c。结果不保证与原始值是同一种 sequence; 例如,包装的列表不保证满足 list?

如果 min-count 是数字,则要求 stream 至少包含那么多元素。

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?
产生一个元素为 stx 的连续子部分的 sequence。 等价于 (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?
返回一个元素为列表的 sequence,每个列表包含 seq 的前 length 个元素, 然后是接下来的 length 个元素,依此类推。

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.