为什么我输入的球拍代码发出any-wrap/c: 预计违反合同:非循环值的信号?

问题描述 投票:0回答:1

在我的 Typed Racket 程序中,我看到此错误:

any-wrap/c: contract violation
  expected: acyclic value
  given: #0=(foo #0#)
  argument position: 1st
  other arguments...:

什么可能导致此错误?

racket typed-racket
1个回答
0
投票

此错误很难诊断,因为通常根本不清楚

any-wrap/c
与发出错误信号的代码有什么关系。

这里的问题与 Typed Racket 中处理

casts
的方式有关。具体来说,以类型
Any
传递的值(最常见的是将类型化 Racket 值传递给非类型化 Racket 的结果)可以获取合约包装器
any-value/c
。如果该值是循环的(即该值内存在引用循环),则
any-wrap/c
合约可能会失败。这是一个例子。这段代码实际上直接使用了
Any
类型,而不是将值传递给无类型的 Racket。

#lang typed/racket

(require typed/rackunit)

(struct foo ([a : Any]) #:transparent #:mutable)

;; create a cyclic 'foo' structure
(define (make-cyclic-structure)
  (define my-foo (foo 13))
  (set-foo-a! my-foo my-foo)
  my-foo)

;; pass a foo as an Any, then cast it and extract the field:
(define (take-any [x : Any]) : Any
  (define its-a-foo (cast x foo))
  (foo-a its-a-foo))

;; this causes the problem:
(take-any (make-cyclic-structure))
;; but so does this:
(check-equal? (make-cyclic-structure) 1234)

在这种情况下,对于两个有问题的行中的第一行有许多修复。最简单的就是将输入的类型从

take-any
更改为
Any
。另一种是将
foo
改为
(cast x foo)
;事实证明,使用
(assert x foo?)
可能会导致值不以相同的方式包装。你也可以使用类似的东西
assert

...这有点笨重,但可以完成工作。

修复第二个(在测试用例中使用)可以通过以下方式完成

(match x [(foo a) x])

...这不太好(失败消息只是报告它想要 true 并且得到 false),但仍然执行正确的测试。

© www.soinside.com 2019 - 2024. All rights reserved.