3

模块:test-define.rkt

#lang racket

(provide test)

(provide (contract-out [add-test! (-> void)]))

(define test 0)

(define (add-test!)
  (set! test (add1 test)))

主程序:act.rkt

#lang racket

(require "test-define.rkt")

(printf "~a~%" test)

(add-test!)

(printf "~a~%" test)

运行 act.rkt,我得到:

0
1

这就是我要的。

但是,如果我在 test-define.rkt 中更改合同:

(provide test)

改成

(provide (contract-out [test integer?]))

然后我再次运行 act.rkt,我得到:

0
0

为什么?我无法更改测试值。

如果我提供一个 get func,它会再次正常。

(provide (contract-out [get-test (-> integer?)]))

(define (get-test)
  test)

如果测试的类型更改为哈希映射,则始终是正常的。

我错过了什么?

4

1 回答 1

4

我注意到在 test-define.rkt 你有这条线

(set! test3 (add1 test))

应该test3test

这可以解释为什么你看到两个零(测试从未改变)。

编辑 2

为方便起见,我将您的两个模块放在同一个文件中并更改了测试合同:

#lang racket
(module test-define racket 
  (provide test)
  ; (provide (contract-out [test integer?]))
  (provide get-test)
  (provide (contract-out [add-test! (-> void)]))
  (define test 0)
  (define (add-test!)
    (set! test (add1 test)))
  (define (get-test)
  test))

(module ack racket
  (require (submod ".." test-define))
  (printf "~a~%" test)
  (add-test!)
  (printf "~a~%" test))

(require (submod "." ack))

现在我看到了 0 1 vs 0 0 输出,就像你一样。

嗯。为什么?

好。如果我们将提供形式更改为根本不使用合约,则输出为 0 1。

添加合同不应该改变这种行为(我认为)。也许是一个错误?

http://pre.racket-lang.org/docs/html/guide/contracts-gotchas.html?q=contract&q=ignore

说:

合同库假定通过合同输出导出的变量没有分配给,但不强制执行。因此,如果您尝试设置!那些变量,你可能会感到惊讶。...snip... Moral:这是我们将在未来版本中解决的错误。

于 2012-07-22T09:15:26.160 回答