In section
, 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.
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:
(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
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
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