9

ラケット/リストのカウントtrue?で使用する関数を定義しました。

(define (true? expr)
  (and (boolean? expr) expr #t))

数値引数を指定すると、関数が喜んで を返すことに気付きました#f

> (true? 6)
#f

そこで、ラケット コントラクトを使用して、非ブール値の引数がコントラクト違反でエラーを返すようにすることを検討しようと考えました。したがって、このコードをファイルの先頭に置きます。

(provide (contract-out
          [true?         (-> boolean? boolean?)]))

ただし、コントラクトを追加した後も、ラケット REPL で上記と同じ動作が得られます。それがどうしてなのか理解できません。私は何が欠けていますか?

4

2 に答える 2

21

コントラクトは通常、モジュール間で適用されます。ですから、外側の視点から試してみる必要があります。ただし、REPL は、作業中のモジュール内から適用されます。

外部からテストする簡単な方法は、テスト サブモジュールを使用することです。例えば:

#lang racket

(define (true? expr)
  (and (boolean? expr) expr #t))

(provide (contract-out
          [true?         (-> boolean? boolean?)]))   

(module* test racket/base
  (require (submod "..")
           rackunit)
  (check-true (true? #t))
  (check-false (true? #f))
  (check-exn exn:fail:contract? (lambda () (true? 3))))

コントラクトを変更して DrRacket で再実行すると、ここにあるtestモジュールがコントラクトの外部顧客として扱われているため、有効なコントラクトがここに表示されます。


または、最初の別のファイルを作成するrequireと、そこでも契約の効果を確認できます。最初のファイルが という名前の場合、true-test.rkt別のモジュールを作成してから、次のことを行うことができます。

 #lang racket
 (require "true-test.rkt")
 (true? 42)  ;; And _this_ should also raise a contract error.
于 2013-02-05T23:02:53.320 に答える
14

Danny Yoo は優れた回答をしました。私はそれを拡張したかっただけで、Racket は契約が施行される場所 (つまり、契約の境界をどこに置くか) についてより柔軟に対応できることに注意してください。たとえば、次のdefine/contract形式を使用できます。

-> (define/contract (true? expr)
     (-> boolean? boolean?)
     (and (boolean? expr) expr #t))

true?の定義と他のすべてのコードとの間の契約チェックを確立します。

-> (true? "foo")
; true?: contract violation
;  expected: boolean?
;  given: "foo"
;  in: the 1st argument of
;       (-> boolean? boolean?)
;  contract from: (function true?)
;  blaming: top-level
;  at: readline-input:1.18
; [,bt for context]

いつもdefine/contractモジュールを持っているとは限らない REPL でコントラクトに関連するものをテストしたい場合に特に便利です。ただし、contract-out通常はモジュール境界でコントラクトをチェックするのが適切な選択であるため、これがデフォルトの推奨事項です。

于 2013-02-06T06:53:32.747 に答える