[previous] [up] [next]     [index]
Next: Processing Two Lists Simultaneously: Up: Processing Two Complex Pieces Previous: Processing Two Lists Simultaneously:

Processing Two Lists Simultaneously: Case 2

In section [cross-reference], we developed the function hours->wages for the computation of weekly wages. It consumed a list of numbers--hours worked per week--and produced a list of weekly wages. We had based the function on the simplifying assumption that all employees received the same pay rate. Even a small company, however, employs people at different rate levels. Typically, the company's accountant also maintains two collections of information: a permanent one that, among other things, includes an employee's personal pay-rate, and a temporary one that records how much time an employee has worked during the past week.

The revised problem statement means that the function should consume two lists. To simplify the problem, let us assume that the lists are just lists of numbers, pay rates and weekly hours. Then here is the problem statement:

;; hours->wages : list-of-numbers list-of-numbers -> list-of-numbers
;; to construct a new list by multiplying the corresponding items on 
;; alon1 and alon2 
;; ASSUMPTION: the two lists are of equal length  
(define (hours->wages alon1 alon2) ...) 
We can think of alon1 as the list of pay-rates and of alon2 as the list of hours worked per week. To get the list of weekly wages, we must multiply the corresponding numbers in the two input lists.

Let's look at some examples:

(hours->wages empty empty)
;; expected value: 
empty 
(hours->wages (cons 5.65 empty) (cons 40 empty))
;; expected value:  
(cons 226.0 empty) 
(hours->wages (cons 5.65 (cons 8.75 empty)) 
                    (cons 40.0 (cons 30.0 empty))) 
;; expected value:  
(cons 226.0 (cons 262.5 empty)) 
For all three examples the function is applied to two lists of equal length. As stated in the addendum to the purpose statement, the function assumes this and, indeed, using the function makes no sense if the condition is violated.

The condition on the inputs can also be exploited for the development of the template. Put more concretely, the condition says that (empty? alon1) is true if, and only if, (empty? alon2) is true; and furthermore, (cons? alon1) is true if, and only if, (cons? alon2) is true. In other words, the condition simplifies the design of the template's cond-structure, because it says the template is similar to that of a plain list-processing function:

(define (hours->wages alon1 alon2)
  (cond 
    ((empty? alon1) ...) 
    (else ... ))) 

In the first cond-clause, both alon1 and alon2 are empty. Hence no selector expressions are needed. In the second clause, both alon1 and alon2 are constructed lists, which means we need four selector expressions:

(define (hours->wages alon1 alon2)
  (cond 
    ((empty? alon1) ...) 
    (else 
      ... (first alon1) ... (first alon2) ... 
      ... (rest alon1) ... (rest alon2) ... ))) 
Finally, because the last two are lists of equal length, they make up a natural candidate for the natural recursion of hours->wages:
(define (hours->wages alon1 alon2)
  (cond 
    ((empty? alon1) ...) 
    (else 
      ... (first alon1) ... (first alon2) ... 
      ... (hours->wages (rest alon1) (rest alon2)) ... ))) 
The only unusual aspect of this template is that the recursive application consists of two expressions, both selector expressions for the two arguments. But, as we have seen, the idea is easily explicable owing to the assumption that alon1 and alon2 are of equal length.


;; hours->wages : list-of-numbers list-of-numbers -> list-of-numbers
;; to construct a new list by multiplying the corresponding items on 
;; ASSUMPTION: the two lists are of equal length  
;; alon1 and alon2 
(define (hours->wages alon1 alon2) 
  (cond 
    ((empty? alon1) empty) 
    (else (cons (weekly-wage (first alon1) (first alon2)) 
                (hours->wages (rest alon1) (rest alon2))))))

;; weekly-wage : number number -> number ;; to compute the weekly wage from pay-rate and hours-worked (define (weekly-wage pay-rate hours-worked) (* pay-rate hours-worked))

Figure: The complete definition of hours tex2html_wrap_inline72204 wage


To define the function from here, we follow the design recipe. The first example implies that the answer for the first cond-clause is empty. In the second one, we have three values available:

  1. (first alon1) evaluates to the first item on the list of pay-rates;
  2. (first alon2) evaluates to the first item on the list of hours worked; and
  3. (hours->wages (rest alon1) (rest alon2)) computes the list of weekly wages for the remainders of alon1 and alon2.
We merely need to combine these values to get the final answer. More specifically, given the purpose statement, we must compute the weekly wage for the first employee and construct a list from that wage and the rest of the wages. This suggests the following answer for the second cond-clause:
(cons (weekly-wage (first alon1) (first alon2))
      (hours->wages (rest alon1) (rest alon2))) 
The auxiliary function weekly-wage consumes the two first items and computes the weekly wage. Figure [cross-reference] contains the complete definitions.


Exercises Exercise 17.2.1

In the real world, hours->wages consumes lists of employee structures and lists of work structures. An employee structure contains an employee's name, social security number, and pay rate. A work structure contains an employee's name and the number of hours worked in a week. The result is a list of structures that contain the name of the employee and the weekly wage.

Modify the function in figure [cross-reference] so that it works on these classes of data. Provide the necessary structure definitions and data definitions. Use the design recipe to guide the modification process. Solution

Exercise 17.2.2

Develop the function zip, which combines a list of names and a list phone numbers into a list of phone records. Assuming the following structure definition:

(define-struct phone-record (name number)) ,
a phone record is constructed with (make-phone-record s n) where s is a symbol and n is a number. Assume the lists are of equal length. Simplify the definition, if possible. Solution


[previous] [up] [next]     [index]
Next: Processing Two Lists Simultaneously: Up: Processing Two Complex Pieces Previous: Processing Two Lists Simultaneously:

PLT