Function signatures

In this course (and in the text) each function definition is preceded by a signature (interchangeably called contract) and a purpose comment. Most of the signatures that we will use in this class can be captured by types and checked by the computer. The informal syntax used by the text for signatures is a close match to the formal syntax of types used by Typed Racket; and can be copied with only small changes. For example, the text gives the following signature, purpose statement, and header for the profit function:

;; profit : number -> number
;; to compute the profit as the difference between revenue and costs
;; at some given ticket-price
(define (profit ticket-price) ...)

The use of ... to specify an incomplete function body is not supported in Typed Racket, so we give the function’s definition when we translate:

(: profit : Number -> Number)
;; to compute the profit as the difference between revenue and costs
;; at some given ticket-price
(define (profit ticket-price)
  (- (revenue ticket-price)
     (cost ticket-price)))

Notice that the only change that we had to make was to change number to Number.

Variable definitions

Variable definitions should also be preceded by a type ascription. The syntax is essentially the same as for functions. For example:

(: e Real)
(define e (exp 1))

(The function exp is built in, and gives the value of e raised to the given power.)

Testing

DrRacket comes with a bundle of tools for testing. There are many of these; the ones that are immediately useful to you are check-expect and check-within, for testing exact and inexact results, respectively. (Other useful checks are check-range and check-error)

The check tools are made available when you require typed/test-engine/racket-tests at the beginning of your program. Once you have included tests in your code, you will need to add the following command at the end of your program:

(test)

This command will cause the tests to run.

For example, we can add tests for the sq function that we defined above:

(: sq (-> Number Number))
;; return the square of a number
;;
(define (sq x)
  (* x x))

(check-expect (sq 5) 25)
(check-expect (sq -1) 1)

When computing with real numbers, the results are often inexact. In that situation we use the check-within form to test if an expression evaluates to within a given delta of an expected result.

(check-within expr-1 expr-2 delta-expr)

For example

(check-within (sq (sqrt 2)) 2 0.001)

Note that the test function runs all of the tests defined up to its invocation. Therefore, you should only invoke it once after all of the tests have been defined.

Querying types

It is possible to query the type of an identifier using DrRacket’s REPL using the :print-type function:

> (:print-type sq)
(-> Number Number)

Notice that Typed Racket prints function types using the prefix syntax. Thus, even if you prefer the more natural infix arrow syntax when you write your own code, you will need to be comfortable with the prefix syntax as well.

Last updated 2020-01-10 10:44:48 -0600
Table of Contents | Back to CS151 Home