

For the last few weeks, we have been discussing different techniques for writing recursive programs, all based on the fundamental technique of structural recursion. Last time, we applied these techniques in writing a recursive program to answer this question about programs in our little language from Session 12: Does a particular variable occur bound in a given piece of code? Our program, (occursbound? var exp), was mutually recursive with the function occursfree? because the definitions of bound and free occurrences are mutually inductive.
In order to think and write more clearly about the little language, we used a new design pattern, Syntax Procedures, which allowed us to focus on the meaning of our data rather than their implementation in Racket.
Today, we practice by solving a problem or three that put to use many of the ideas we have learned about Racket, functional programming, and recursive programming. These problems will also be more realistic: you'll have to flesh our some of the details yourself.
Some of you have noticed that many of the functions you've written this semester have assumed that we could apply a given function to every member of a list. If we can't we won't find out until runtime, because Racket is dynamically typed. Can we do differently? Let's write some functions that enable us to check for valid data before launching into the body of a function.
First, let's design a function named (typesmatch? types values), where
> (define typesignature (list number? string?)) > (typesmatch? typesignature '(42 "Hello, Eugene")) #t
To support variable arity, let's add one condition: If there are fewer types than values, the function uses the last predicate in types to validate all of the remaining arguments.
Your tasks:
Work in groups of two or three to think through the problem and create your solutions. Ask for clarification if there is some part of the problem you don't understand.
Data types:
values is a standard list: lst ::= ()  (any . lst) types is too, but...  only empty if values is, too  otherwise, if we ever run out of types, we use the last type over  so may be better to think of it as a list with *at least 1* type or pull out first type and then have standard list this tells us how to think about our test cases (and, later, how to write the code)
Test cases:
()() + { true, false } x { (n)(n), (n)(>n) } (build them from example above)
typesmatch? has an error case: it receives no types and at least one value. So our code needs to throw a Racket error.
We have seen Racket's primitive error function a couple of times. It allows our code to signal Racketlike errors. You can pass to error one of three sets of arguments:
> (error 'typesmatch?) error: typesmatch? > (error "type mismatch") type mismatch > (error 'typesmatch? "must have at least one type") typesmatch?: must have at least one type
If you want to read more about the function, check out the Racket documentation.
Write the structurally recursive function named (typesmatch? types values), where
For example:
> (define typesignature (list number? string?)) > (typesmatch? typesignature '(42 "Hello, Eugene")) #t > (typesmatch? typesignature '(42 'eugene)) #f > (typesmatch? typesignature '(42 "Hello" "Eugene")) #t > (typesmatch? typesignature '(42 "Hello" 'eugene)) #f > (typesmatch? '() '()) #t
You may use higherorder functions such as map wherever they are appropriate. You may find the function every? useful. We wrote this predicate for Homework 4.
interface for special cases  I use this opportunity to pass (first types) (rest types) to worker  now, I can watch for empty types and have the last type handy!  check for error case, too helper function that is structurally recursive  the base case maps the last type type over the remaining values  the pair case "and" recursively how do we test the error case? more later...
(lambda args <body>)When this function is called, args is a parameter bound to a list that contains all the arguments passed to the function.
Our next exercise asks you to write a new kind of variablearity function. Sometimes, we want the function to take one or more specific arguments and then allow zero or more additional arguments. We will give specific names to the specific arguments and then gather any remaining arguments into a list.
For example, suppose that I wanted to define a function named foo that takes one function followed by any number of other arguments:
(foo + 1 2 3 4 ...)
We can do this using another variation on lambda's first argument:
(define foo (lambda (f . args) <body>))
This parameter signature says to bind f to the first argument passed to the function and to bind args to a list containing the rest of the arguments. In our example, f will be bound to the value of +, and args will be bound to the list (1 2 3 4 ...).
You can list any number of names before the ., and each name will be bound to the corresponding argument, with all remaining args put in a list and bound to the name after the dot.
(Yes, that's the same dot notation we learned about in Session 4... Can you figure out how it makes sense here?)
With the typesmatch? function in hand, we can now create Racket functions that check the types of their arguments before attempting to evaluate.
Write a function named typechecked that takes as arguments a function f and zero or more type predicates, t_{1}?, t_{2}?, ....
typechecked returns a variablearity function that works like this:
For example:
> ((typechecked sqrt number?) 100) 10 > (define safesqrt (typechecked sqrt number?)) > (safesqrt 144) 12 > (safesqrt "144") typechecked: type mismatch ("144") > (define safe+ (typechecked + number?)) > (safe+ 1 2 3 4 5) 15 > (safe+ 1 2 'a 4 5) typechecked: type mismatch (1 2 a 4 5) > (define safemap (typechecked map procedure? list?)) > (safemap sqrt '(1 4 9 16)) '(1 2 3 4) > (safemap 'sqrt '(1 4 9 16)) ; that's a symbol! typechecked: type mismatch: (sqrt (1 4 9 16))
typechecked is not recursive. It is simply a higherorder function that uses a recursive function you have already written, typesmatch?.
You may generate a more helpful error message if you like. There is room for improvement!
Let's take this step by step. typechecked takes as arguments a function f and zero or more type predicates:
(define typechecked (lambda (f . types) ...))
The value of typechecked is a variablearity function:
(define typechecked (lambda (f . types) (lambda args ...)))
When the returned function is called, if its arguments match the types given to typechecked, then it returns the value of f(x_{1}, x_{2}, ...):
(define typechecked (lambda (f. types) (lambda args (if (typesmatch? types args) (apply f args) ...))))
Otherwise, it reports an error. So:
(define typechecked (lambda (f. types) (lambda args (if (typesmatch? types args) (apply f args) (error 'typechecked "type mismatch: ~a" args)))))
Baby steps take us to a solution. Notice: typechecked doesn't do any work to check the types of any arguments; it can't, because it doesn't receive those arguments. It returns function a function that does receive arguments and that uses typesmatch? to check them.
The functions typechecked and typesmatch? show that type checking can be thought of as a decoration on a function definition. With a little bit more work, we could create a new special form named, say, lambdatyped, that lets programmers define types for their formal parameters in much the same way as we do in any staticallytyped language. We could even have this special form apply the type checking at definition time, rather than run time, in order to provide the static typing that you all know and love.
Using a simple language that allows userdefined extensions is a great way for us to see how the underlying mechanics of our more complex languages work: we implement the mechanics in our own language!
In both of our functions today, we have a new kind of situation to deal with. Sometimes, a function must generate an error. How do we test to see that our function causes an error that we expect?
Consider the cases we saw above:
> (define safesqrt (typechecked sqrt number?)) > (safesqrt 144) 12 > (safesqrt "144") typechecked: type mismatch ("144")
We have been using rackunit to write unit tests that check to see if our code returns the correct answer. It is easy to check our first safesqrt case using checkequal?:
(checkequal? ((typechecked sqrt number?) 144) 12)
We need something more powerful than checkequal? for the second case. First of all, there is no value for us to compare to (safesqrt "144"). Second, even if there were, our application of safesqrt will cause an error before we can do the comparison, interrupting the check! Our test case needs to indicate that the case fails if it doesn't cause an error!
rackunit provides another primitive to do just that, called checkexn. Here is how we might use it to test safesqrt:
(checkexn exn:fail? (lambda () (safesqrt "100")))
exn:fail? is the name of the kind of error that the error function throws. We wrap our call to safesqrt in a lambda, so that Racket can control when it gets called and capture the result. 0argument lambda expressions of this kind are used to delay computation in many situations, so much so that the idea has its own name: thunk.
It turns out that rackunit offers us a lot more than equality testing. For example, it also allows us to give a string as the last argument to any check, in order to customize the message it displays when a test fails. I use optional string arguments such as "handles oneargument function" in the tests for today's code. If you would like to learn more, check out the RackUnit API in the online documentation, or the documentation in your Racket application.