Определение контрактов на ракетку с помощью пользовательского предиката

Я только начинаю узнавать о контрактах (через exercism.io), и поэтому я заключил контракт, который:

[step1 (-> (and/c number?
                  less-than-one-hundred?)
            string?)]

То, что я думаю, я говорю, что функция будет принимать число меньше ста (эта функция определяется как:

(define (less-than-one-hundred? n)
  (< n 100))

Но когда я вызываю функцию так:

(step1 100)

Нет нарушения договора. Что я делаю неправильно?

2 ответа

Решение

Вот конкретный пример того, что говорит ответ Soegaard:

DEF-step1.rkt

#lang racket

(provide (contract-out
          [step1 (-> (and/c number?
                            less-than-one-hundred?)
                     string?)]))

(define (less-than-one-hundred? n)
  (< n 100))

(define (step1 x) "")

потребительная step1.rkt

#lang racket

(require "def-step1.rkt")

(step1 100)

Это приводит к нарушению контракта, как вы ожидаете, и, в частности, он обвиняет use-step1.rkt, другая "сторона контракта", чем def-step1.rkt откуда пришел контракт:

step1: contract violation
  expected: less-than-one-hundred?
  given: 100
  in: an and/c case of
      the 1st argument of
      (->
       (and/c number? less-than-one-hundred?)
       string?)
  contract from: .../def-step1.rkt
  blaming: .../use-step1.rkt
   (assuming the contract is correct)

Контракты применяются только через границы модуля. Это означает, что если ваше выражение (step1 100) находится в том же модуле, что и контракт, вход не проверяется.

Однако если вы экспортируете step1 с контрактом, а затем в другом модуле импорта step1 и называет его, договор будет проверен.

Другие вопросы по тегам