Hand evaluation is just the normal algebraic evaluation of an expression:
(+ 4 (sqrt 25))
= (+ 4 5)
= 9
or suppose
(define (pizza_area d) (* d d)) ; square pizza!
(define (pizza_cost d) (* .75 (pizza_area d)))
then
(pizza_cost 4)
=(* .75 (pizza_area 4))
=(* .75 (* 4 4))
=(* .75 16)
= 12
Notice how every expression and function is expanded and evaluated in its place.
Last lecture we talked about the importance of contracts to the definition of functions. Let's try to formalize the design process of a function into the following 4 steps (we'll discuss each piece in a minute):
Here's an example:
;; F_to_C: num --> num
;; F_to_C calculates the Celsius temperature corresponding
;; to the given Farenheit temperature(define (F_to_C f)
( * (/ 5 9) (- f 32)) )
(= 0 (F_to_C 32))
(= 100 (F_to_C 212))
(= -40 (F_to_C -40))Output:
true
true
true
Let's examine each piece of the design recipe:
Write the contract, purpose and header
Develop examples/test code
Why is this done before the actual body of the function is written?
To the user of the function, does it matter how the function accomplishes its goals? How does this relate to the goal of abstracting the problem?
This concept of information and process hiding is called "encapsulation" and is one of the cornerstones of abstract modeling.
The test code is written such that it will return true if the expected output of the function is equal to its actual output.
Write the body of the function
Here's where the rubber meets the pavement.
The better you've done the rest of the design recipe, the easier this part will be. We will come up with some design templates later that will help us here.
Test the function
This is where you mess up good theory with experiment. Hopefully all you will get back is a bunch of "true"'s when you run your test code.
There are times when one needs to make a decision in a program. That is, one needs to do one thing in a particular situation and another thing if we are not in that situation.
Boolean (true/false) values are very useful for helping us make decisions. That is, if a given boolean value is true we do one thing, or if it is false, we something else.
Conditional operators (functions) are used to compare values and produce booleans: >, <, =, >=, <=
Boolean operators are used to combine booleans: and, or.not, nand, nor, etc.
Scheme has a function called cond that does just this:
(cond
[(boolean expression #1) (expression #A)]
[(boolean expression #2) (expression #B)]
...
[else (expression #Z)])
The process is:
The else is very important because it ensures that the cond function will always return something valid.
Example:
;; donut_cost: num -> num
;; calculates the cost for donuts at $0.50/ea for and order of 1-10,
;; $0.40/ea for and order of 11-20 and
;; $0.30/ea for an order of greater than 20.(define (donut_cost n)
(cond
[(<= n 10) (* 0.5 n)]
[(<= n 20) (* 0.4 n)]
[else (* 0.3 n)]))( = 2.50 (donut_cost 5))
( = 6.00 (donut_cost 15))
( = 15 (donut_cost 50))
©2002 Stephen Wong