CSC 153 Grinnell College Spring, 2009
 
Computer Science Fundamentals
 

Procedures as First-Class Citizens

Goals

This laboratory exercise provides practice with procedures:

Procedures as Arguments, map, apply, and eval

Consider the following procedure every? that takes two arguments, a predicate pred and a list ls, and determines whether or not the predicate is true of every element of the list.

(define every?
   (lambda (pred ls)
   ;Pre-condition:  pred is a procedure; ls is a list
   ;Post-conditions:  returns error if pre-conditions are not met
   ;                  returns #t if pred is true for every element of list
     ; precondition tests
     (if (not (procedure? pred))
         (error 'every? "The first argument must be a predicate"))
     (if (not (list? ls))
         (error 'every? "The second argument must be a list"))
     (every-kernel pred ls)))

(define every-kernel
   (lambda (pred ls)
   ;Pre-condition:  pred is a procedure; ls is a list
   ;Post-conditions:  returns #t if pred is true for every element of list 
      (or (null? ls)
          (and (pred (car ls))         ; Invoke the predicate here!
               (every-kernel pred (cdr ls))))))
  1. Using every? as a model, write and test an analogous procedure any? that determines whether a given predicate is true of at least one element of a given list. (Note: every? returns #t if it is given an empty list; any? should return #f in this case.)

  2. Consider the following procedure capitalize that capitalizes all letters in a string:

    (define capitalize
       (lambda (str)
       ;Pre-condition:  str is a character string
       ;Post-condition:  str is returned with all letters capitalized
           (list->string (map char-upcase (string->list str)))
        )
    )
    

    Run capitalize on several strings to test precisely what it does.

  3. Explain in a few sentences what capitalize does.

  4. The map procedure can actually take more than two arguments, if all of the extras are lists:

    > (map string-append '("left" "start" "beginning")
                         '("-to-" "-to-" "-to-")
                         '("right" "finish" "end"))
    ("left-to-right" "start-to-finish" "beginning-to-end")
    
    

    Define a procedure pairwise-sum that takes as arguments two lists of numbers, equal in length, and returns a new list whose components are the sums of the corresponding components of the arguments. Define this procedure using map.

  5. Define a procedure dot-product that takes as arguments two lists of numbers, equal in length, and returns the sum of the products of corresponding elements of the arguments:

    > (dot-product '(3 4 -1) '(1 -2 -3))
    -2
    
    > (dot-product '(0.003 0.035) '(8 2))
    0.094
    
    > (dot-product '(5.3e4) '(2.0e-3))
    106.0
    
    > (dot-product '() '())
    0
    

    Use apply and map to give a concise definition of this procedure.

  6. Write a procedure do-it that reads an expression, evaluates it, and prints the result -- paralleling one pass through the read-eval-print cycle.

  7. Modify do-it so that it reads, evaluates, and prints multiple expressions, until the user types (exit).


This document is available on the World Wide Web as

http://www.cs.grinnell.edu/~walker/courses/153.sp09/labs/lab-procedure-arguments.shtml

created 24 March 1997 by John David Stone
last revised 2 April 2008 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.