1

I'm just starting to learn about contracts (via exercism.io) and so I have made a contract that is:

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

What I think I'm saying is the function will take a number less than one hundred (which is a function defined as:

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

But when I call the function like this:

(step1 100)

No contract violation. What am I doing wrong?

robertpostill
  • 3,820
  • 3
  • 29
  • 38

2 Answers2

2

Contracts are only enforced over module boundaries. This means that if your expression (step1 100) is in the same module as you contract, the input is not checked.

However if you export step1 with a contract, and then in another module imports step1 and calls it, the contract will be checked.

soegaard
  • 30,661
  • 4
  • 57
  • 106
2

Here's a concrete example of what Soegaard's answer is saying:

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) "")

use-step1.rkt

#lang racket

(require "def-step1.rkt")

(step1 100)

This produces a contract violation like you expect, and in particular, it blames use-step1.rkt, a different "contract party" than def-step1.rkt where the contract came from:

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)
Alex Knauth
  • 8,133
  • 2
  • 16
  • 31