Lists can contain more than one kind of data. Consider as a simple example a list containing both numbers and symbols. The data definition for such a list is as follows: A list-of-nums-and-syms is one of - empty - (cons S lons) where S is a symbol and lons is a list-of-nums-and-syms - (cons N lons) where N is a symbol and lons is a list-of-nums-and-syms We could use such a list to represent a recipe. Each symbol names an ingredient and each number indicates how long to cook before adding the next ingredient. Example of data: (cons 'garlic (cons 'cumin (cons 5 (cons 'beans (cons 10 empty))))) What does the template for a program over list-of-nums-and-syms look like? (define (... a-lons ...) (cond [(empty? a-lons) ...] [(symbol? (first a-lons)) ... (first a-lons) ... (rest a-lons) ... ] [(number? (first a-lons)) ... (first a-lons) ... (rest a-lons) ... ])) Let's write several programs over list-of-nums-and-syms: ;; cook-time : lons -> num ;; sum up all the numbers in the list (define (cook-time a-lons) (cond [(empty? a-lons) 0] [(symbol? (first a-lons)) (cook-time (rest a-lons))] [(number? (first a-lons)) (+ (first a-lons) (cook-time (rest a-lons)))])) ;; ingredient-count : lons -> num ;; count how many symbols are in the list (define (ingredient-count a-lons) (cond [(empty? a-lons) 0] [(symbol? (first a-lons)) (+ 1 (ingredient-count (rest a-lons)))] [(number? (first a-lons)) (ingredient-count (rest a-lons))])) ;; no-cook-recipe? : lons -> bool ;; returns true if there are no numbers in the list (define (no-cook-recipe? a-lons) (cond [(empty? a-lons) true] [(symbol? (first a-lons)) (no-cook-recipe? (rest a-lons))] [(number? (first a-lons)) false])) Notice how similar these programs are! The structure of the data determines a large portion of the program. By using the design recipes, you can write large portions of your programs without thinking about what the programs actually do. ;; get-ingredients : lons -> list-of-symbols ;; extracts a list of the symbols in the list (define (get-ingredients a-lons) (cond [(empty? a-lons) empty] [(symbol? (first a-lons)) (cons (first a-lons) (get-ingredients (rest a-lons)))] [(number? (first a-lons)) (get-ingredients (rest a-lons))])) ;; substitute : lons sym sym -> lons ;; replaces all uses of the first symbols with the second symbol (define (substitute a-lons old-sym new-sym) (cond [(empty? a-lons) empty] [(symbol? (first a-lons)) (cond [(symbol=? (first a-lons) old-sym) (cons new-sym (substitute (rest a-lons) old-sym new-sym))] [else (cons (first a-lons) (substitute (rest a-lons) old-sym new-sym))])] [(number? (first a-lons)) (cons (first a-lons) (substitute (rest a-lons) old-sym new-sym))])) These last two programs return lists, rather than atomic data such as numbers and booleans. Notice that they don't look much different from the earlier programs. Again, the template drives the definition of the program.