Function template

The template is a "first draft" of the function body, comprising all the code you can write based simply on the types of the data involved in the problem. Once you've done this, you just need to fill in a few blanks by actually thinking about the problem to be solved.

There are several different sorts of templates, depending on how complex the data are. In addition, you can develop templates based on either the input data types or the output data type.

Input templates

Input templates allow you to reason about the information your function is given. If the function might receive any of several different things, it allows you to make sure you've handled any possibility; if the function might receive a complex datum made up of smaller pieces, it allows you to get at the pieces.
  1. All parameters are of simple types
  2. Several cases
  3. Compound data type (e.g. a structure defined with "define-struct")
  4. Several different types
  5. Checking input errors
  6. Lists of Unknown Length
  7. Natural Numbers
  8. Other self-referential data structures
  9. Multiple inputs of complex types

Output templates

Output templates allow you to reason about the kind of result your function is supposed to produce. They allow you to make sure all the possible outputs can in fact be produced, and if the function is supposed to return a complex datum, they help you to build it.
  1. Output is of a simple type
  2. Output is one of several possibilities
  3. Output is of a compound data type (e.g. a structure defined with "define-struct")
  4. Output is one of several different types
  5. Lists of unknown length
  6. Natural numbers
  7. Other self-referential data structures

Combining Input and Output Templates

After you've analyzed both the input and output data types of your function, you still need to decide what kind of template to use.
If both input and output types are simple,
neither template will give you a lot of information. The input-based template tells you to use your parameters, and the output-based template tells you what type the resulting expression should be. You're on your own from here.
If the input types are all fairly simple, and the output type isn't,
use an output-based template.
If the output type is fairly simple, and at least one input type isn't,
use an input-based template.
If both input and output types are complex,
you may need to combine input-based and output-based templates. Very often, the input-based template gives you clues to the questions in each clause of a cond, while the output-based template gives clues to the answers. In this case, you just need to match up the correct question with the correct answer, and your work is almost done.
For example, if your function takes in a list and produces another list, the input template tells you that if the input is a non-empty list, you'll probably be calling the same function on the rest of the list, while the output template tells you that you'll probably be cons-ing some single element onto the result of calling the same function on somethingorother.

Input template

(define (func my-list)
   (cond [(empty? my-list) ...]
         [(cons? my-list)
          ... (first my-list) ...
          ... (func (rest my-list)) ...]))

Output template

(define (func my-list)
   (cond [... empty]
         [... (cons some-element
                    (func some-list))]))

Likely merged template

(define (func my-list)
   (cond [(empty? my-list) empty]
         [(cons? my-list)
          (cons ( ... (first my-list) ...)
                (func (rest my-list)))]))

Last modified: Thu Dec 12 14:04:08 EST 2002
Stephen Bloch / sbloch@adelphi.edu