球拍 - 预期:顺序?给定:#<sequence> 违约

Racket - expected: sequence? given: #<sequence> contract violation

在球拍中使用生成器和模式匹配我 运行 在练习懒惰地解构集合时遇到以下错误,我无法弄清楚错误是什么,也不知道为什么会发生。

  (require racket/match)
  (require racket/generator)
  (require data/collection)
  (sequence->list
   (in-generator
    (let recur ([seq '(1 2 3)])
      (match seq
        [(sequence) (void)]
        [(sequence next next-rest ...)
         (yield next)
         (recur next-rest)]))))

出现以下错误:

sequence->list: contract violation
  expected: sequence?
  given: #<sequence>
  in: the 1st argument of
      (-> sequence? (listof any/c))
  contract from: 
      <pkgs>/collections-lib/data/collection/collection.rkt
  blaming: /var/folders/g4/0st3r3c513n6ymf2nkw11ml40000gn/T/ob-racket-CFPotf
   (assuming the contract is correct)
  at: <pkgs>/collections-lib/data/collection/collection.rkt:64.3
  context...:
   /usr/local/Cellar/minimal-racket/7.7/share/racket/collects/racket/contract/private/blame.rkt:347:0: raise-blame-error
   /usr/local/Cellar/minimal-racket/7.7/share/racket/collects/racket/contract/combinator.rkt:324:9
   /usr/local/Cellar/minimal-racket/7.7/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   "/var/folders/g4/0st3r3c513n6ymf2nkw11ml40000gn/T/ob-racket-CFPotf": [running body]
   temp35_0
   for-loop
   run-module-instance!
   perform-require!

没有生成器,如果我只是做 (cons next (recur next-rest)) 一切正常,所以它不应该与我的模式匹配代码有任何关系。但话又说回来,我对生成器非常有信心并且已经做过很多次这样的事情,只是没有模式匹配位。我很确定这个 应该 工作,但不知道为什么我会收到这个错误,甚至不知道它意味着什么。

这是因为 data/collectionsequence 的概念与 racket 中的 sequence 略有不同。 data/collection 中的 sequence->list 函数并不总是适用于 racketracket/generator 中的序列,因此您需要使用 [=14] 中的 sequence->list =] 代替。

一种方法是避免从 data/collection:

导入 sequence->list
#lang racket
(require racket/match)
(require racket/generator)
(require (except-in data/collection sequence->list))
(sequence->list
 (in-generator
  (let recur ([seq '(1 2 3)])
    (match seq
      [(sequence) (void)]
      [(sequence next next-rest ...)
       (yield next)
       (recur next-rest)]))))

这会产生 '(1 2 3) 而不是您遇到的错误。

解决此问题的另一种方法是将 sequenceracket 概念转换为更接近 racketdata/collection 版本] stream 的概念。您可以使用 sequence->stream.

#lang racket
(require racket/match)
(require racket/generator)
(require data/collection)
(sequence->list
 (sequence->stream
  (in-generator
   (let recur ([seq '(1 2 3)])
     (match seq
       [(sequence) (void)]
       [(sequence next next-rest ...)
        (yield next)
        (recur next-rest)])))))

这也会产生 '(1 2 3).

sequence->listsequence->stream 似乎多余,但更像是 data/collection-sequence->listracket-sequence->data/collection-sequence

虽然必须携带 2 个不同的序列概念,而两者都被称为“序列”,这有点不方便。如果你愿意,你可以导入带有前缀的 data/collection 东西以将它们标记为单独的,例如 dc:

#lang racket
(require racket/match)
(require racket/generator)
(require (prefix-in dc: data/collection))
(sequence->list
 (in-generator
  (let recur ([seq '(1 2 3)])
    (match seq
      [(dc:sequence) (void)]
      [(dc:sequence next next-rest ...)
       (yield next)
       (recur next-rest)]))))

根据项目其余部分的外观,您可能需要不同的风格。