#lang scribble/doc
@(require scribble/manual
          scribble/eval
          "guide-utils.ss"
          "contracts-utils.ss"
          (for-label scheme/contract))

@title[#:tag "contract-func"]{Simple Contracts on Functions}

When a module exports a function, it establishes two
channels of communication between itself and the client
module that imports the function. If the client module calls
the function, it sends a value into the ``server''
module. Conversely, if such a function call ends and the
function returns a value, the ``server'' module sends a
value back to the ``client'' module.

It is important to keep this picture in mind when you read the explanations
of the various ways of imposing contracts on functions. 

@ctc-section[#:tag "argcontract"]{Restricting the Arguments of a Function}

Functions usually don't work on all possible Scheme values but only on a
select subset such as numbers, booleans, etc. Here is a module that may
represent a bank account: 

@schememod[
scheme

(provide/contract 
  [create  (-> string? number? any)]
  [deposit (-> number? any)])

(define amount 0)
(define (create name initial-deposit) ...)
(define (deposit a) (set! amount (+ amount a)))
]

It exports two functions: 
@itemize[

@item{@scheme[create]: The function's contract says that it consumes two
arguments, a string and a number, and it promises nothing about the return value. }

@item{@scheme[deposit]: The function's contract demands from the client modules
that they apply it to numbers.  It promises nothing about the return value. }]

If a ``client'' module were to apply @scheme[deposit] to
@scheme['silly], it would violate the contract.  The
contract monitoring system would catch this violation and
blame ``client'' for breaking the contract with the above
module.

@bold{Note:} Instead of @scheme[any] you could also use the
more specific contract @scheme[void?], which says that the function will
always return the @scheme[(void)] value. This contract, however, would require
the contract monitoring system to check the return value every time the function
is called, even though the ``client'' module can't do much with this value
anyway. In contrast, @scheme[any] tells the monitoring system @italic{not}
to check the return value. Additionally, it tells a potential client that the
``server'' module @italic{makes no promises at all} about the function's return
value.

@ctc-section[#:tag "arrow"]{Arrows}

It is natural to use an arrow to say that an exported value is a
function. In decent high schools, you learn that a function has a domain
and a range, and that you write this fact down like this: 
@schemeblock[
f : A -> B
]
Here the @scheme[A] and @scheme[B] are sets; @scheme[A] is the
domain and @scheme[B] is the range. 

Functions in a programming language have domains and ranges, too. In
statically typed languages, you write down the names of types for each
argument and for the result. When all you have, however, is a Scheme name,
such as @scheme[create] or @scheme[deposit], you want to tell the
reader what the name represents (a function) and, if it is a function (or
some other complex value) what the pieces are supposed to be. This is why
we use a @scheme[->] to say ``hey, expect this to be a function.''

So @scheme[->] says ``this is a contract for a function.'' What follows
in a function contracts are contracts (sub-contracts if you wish) that tell
the reader what kind of arguments to expect and what kind of a result the
function produces. For example, 
@schemeblock[
(provide/contract
 [create (-> string? number? boolean? account?)])
]
says that @scheme[create] is a function of three arguments: a string, a
number, and a boolean. Its result is an account. 

In short, the arrow @scheme[->] is a @italic{contract
combinator}. Its purpose is to combine other contracts into a contract
that says ``this is a function @italic{and} its arguments and its result
are like that.''

@ctc-section[#:tag "dots"]{Infix Contract Notation}

If you are used to mathematics, you like the arrow in between the
  domain and the range of a function, not at the beginning. If you
  have read @|HtDP|, you have seen this many times. Indeed, you may
  have seen contracts such as these in other people's code:

@schemeblock[
(provide/contract
  [create (string? number? boolean? . -> . account?)])
]

If a PLT Scheme S-expression contains two dots with a symbol in the middle,
the reader re-arranges the S-expression and place the symbol at the front. Thus, 
@schemeblock[
(string? number? boolean? . -> . account?)
]
is really just a short-hand for 
@schemeblock[
(-> string? number? boolean? account?)
]
Of course, placing the arrow to the left of the range follows not only
mathematical tradition but also that of typed functional languages. 

@ctc-section[#:tag "own"]{Rolling Your Own Contracts for Function Arguments}

The @scheme[deposit] function adds the given number to the value of
@scheme[amount]. While the function's contract prevents clients from
applying it to non-numbers, the contract still allows them to apply the function
to complex numbers, negative numbers, or inexact numbers, all of which do not
represent amounts of money. 

To this end, the contract system allows programmers to define their own
contracts: 

@schememod[
scheme
  
(define (amount? a)
  (and (number? a) (integer? a) (exact? a) (>= a 0)))

(provide/contract
  (code:comment "an amount is a natural number of cents")
  (code:comment "is the given number an amount?")
  [deposit (-> amount? any)]
  [amount? (-> any/c boolean?)])
  
(define this 0)
(define (deposit a) (set! this (+ this a)))
]

The module introduces a
predicate, @scheme[amount?]. The @scheme[provide]
clause refers to this predicate, as a contract, for its
specification of the contract of
@scheme[deposit].

Of course it makes no sense to restrict a channel of
communication to values that the client doesn't
understand. Therefore the module also exports
the @scheme[amount?] predicate itself, with a contract
saying that it accepts an arbitrary value and returns a
boolean.

In this case, we could also have used @scheme[natural-number/c], which
is a contract defined in @schememodname[scheme/contract] that is
equivalent to @scheme[amount] (modulo the name):

@schememod[
scheme

(provide/contract
  (code:comment "an amount is a natural number of cents")
  [deposit (-> natural-number/c any)])
  
(define this 0)
(define (deposit a) (set! this (+ this a)))
]

Lesson: learn about the built-in contracts in @schememodname[scheme/contract]. 

@ctc-section[#:tag "and-or"]{The @scheme[and/c], @scheme[or/c], and @scheme[listof] Contract Combinators}

Both @scheme[and/c] and @scheme[or/c] combine contracts and
they do what you expect them to do.

For example, if we didn't have @scheme[natural-number/c], the
@scheme[amount?] contract is a bit opaque. Instead, we would define it
as follows: 

@schememod[
scheme

(define amount 
  (and/c number? integer? exact? (or/c positive? zero?)))

(provide/contract
  (code:comment "an amount is a natural number of cents")
  (code:comment "is the given number an amount?")
  [deposit (-> amount any)])
  
(define this 0)
(define (deposit a) (set! this (+ this a)))
]

That is, amount is a contract that enforces the following conditions: the
value satisfies @scheme[number?] and @scheme[integer?] and
@scheme[exact?] and is either @scheme[positive?] or
@scheme[zero?].

Oh, we almost forgot. What do you think @scheme[(listof char?)]
means? Hint: it is a contract!

@ctc-section[#:tag "range"]{Restricting the Range of a Function}

Consider a utility module for creating strings from banking records: 

@schememod[
scheme

(define (has-decimal? str)
  (define L (string-length str))
  (and (>= L 3)
       (char=? #\. (string-ref str (- L 3)))))

(provide/contract
  (code:comment "convert a random number to a string")
  [format-number (-> number? string?)]

  (code:comment "convert an amount into a string with a decimal")
  (code:comment "point, as in an amount of US currency")
  [format-nat (-> natural-number/c
                  (and/c string? has-decimal?))])
]
The contract of the exported function @scheme[format-number] specifies that
the function consumes a number and produces a string.

The contract of the exported function @scheme[format-nat] is more
interesting than the one of @scheme[format-number].  It consumes only
natural numbers. Its range contract promises a string that has a
@litchar{.} in the third position from the right.

@(exercise) Strengthen the promise of the range contract for
@scheme[format-nat] so that it admits only strings with digits and a single
dot. 

@(solution)

@schememod[
scheme

(define (digit-char? x) 
  (member x '(#\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\0)))

(define (has-decimal? str)
  (define L (string-length str))
  (and (>= L 3)
       (char=? #\. (string-ref str (- L 3)))))

(define (is-decimal-string? str)
  (define L (string-length str))
  (and (has-decimal? str)
       (andmap digit-char?
               (string->list (substring str 0 (- L 3))))
       (andmap digit-char?
               (string->list (substring str (- L 2) L)))))

(provide/contract
  ...
  (code:comment "convert a number to a string")
  [format-number (-> number? string?)]
  
  (code:comment "convert an  amount (natural number) of cents")
  (code:comment "into a dollar based string")
  [format-nat (-> natural-number/c 
                  (and/c string? 
                         is-decimal-string?))])
]


@ctc-section[#:tag "coercion"]{Contracts Coerced from Other Values}

The contract library treats a number of Scheme values as if they are
contracts directly. We've already seen one main use of that: predicates. Every
function that accepts one argument can be treated as a predicate
and thus used as a contract.

But many other values also play double duty as contracts.
For example, if your function accepts a number or @scheme[#f],
@scheme[(or/c number? #f)] sufficies. Similarly, the @scheme[result/c] contract
could have been written with a @scheme[0] in place of @scheme[zero?].

Even better, if you use a regular expression as a contract, the contract
accepts strings that match the regular expression. For example, 
the @scheme[is-decimal-string?] predicate could have been written
@scheme[#rx"[0-9]*\\.[0-9][0-9][0-9]"].

@ctc-section{Contracts on Higher-order Functions}

Function contracts are not just restricted to having simple
predicates on their domains or ranges. Any of the contract
combinators discussed here, including function contracts
themselves, can be used as contracts on the arguments and
results of a function.

For example, 
@schemeblock[(-> integer? (-> integer? integer?))]
is a contract that describes a curried function. It matches
functions that accept one argument and then return another
function accepting a second argument before finally
returning an integer.

This contract
@schemeblock[(-> (-> integer? integer?) integer?)]
describes functions that accept other functions as inputs.

@ctc-section{The Difference Between @scheme[any] and @scheme[any/c]}

The contract @scheme[any/c] accepts any value, and
@scheme[any] is a keyword that can appear in the range of
the function contracts (@scheme[->], @scheme[->*], and
@scheme[->d]), so it is natural to wonder what the
difference between these two contracts is:
@schemeblock[
(-> integer? any)
(-> integer? any/c)
]

Both allow any result, right? There is one important difference:
in the first case, the function may return anything at
all, including multiple values. In the second case, the
function may return any value, but not more than one. For
example, this function:
@schemeblock[
(define (f x) (values (+ x 1) (- x 1)))
]
meets the first contract, but not the second one.}

