CS61A
Week 14 solutions
HOMEWORK:

4.25
UNLESS in normal vs. applicative order
In ordinary (applicative order) Scheme, this version of FACTORIAL
will be an infinite loop, because the argument subexpression
(* n (factorial ( n 1))) is evaluated before UNLESS is called,
whether or not n is 1.
In normal order Scheme it'll work fine, because the argument
subexpressions aren't evaluated until they're needed.
What
will actually happen is that each use of the special form IF
within UNLESS will force the computation of (= n 1), but
no multiplications will happen until the evaluator tries to
print the result.
In effect, (factorial 5) returns the thunk
(lambda () (* 5 (* 4 (* 3 (* 2 (* 1 1))))))
and that gets evaluated just in time to print the answer.
4.26
Normal order vs. special forms
For Ben's side of the argument we must implement UNLESS as a
derived expression:
(define (unless>if exp)
(makeif (unlesspredicate exp)
(unlessconsequent exp)
(unlessalternative exp)))
(define unlesspredicate cadr)
(define unlessalternative caddr)
(define unlessconsequent cadddr)
Notice that we reversed the order of the last two subexpressions in
the call to makeif.
Then we just add a clause
((unless? exp) (eval (unless>if exp) env))
to the ordinary metacircular evaluator, or
((unless? exp) (analyze (unless>if exp)))
to the analyzing evaluator.
For Alyssa's side of the argument, we need a case in which it's useful to
have a Scheme special form available as an ordinary procedure.
The only
thing we can do with ordinary procedures but not with special forms is use
them as arguments to higherorder procedures.
An example using UNLESS will
be a little strained, so first we'll look at a more common situation
involving a different special form, namely AND.
We'd like to be able to say
(define (alltrue? tflist)
(accumulate and tflist))
Now, here's the strained example using UNLESS:
Suppose we have a list of
truefalse values and we'd like to add up the number of true ones.
Here's a
somewhat strange way to do it:
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
(define zerolist (cons 0 '()))
(setcdr! zerolist zerolist)
(define onelist (cons 1 '()))
(setcdr! onelist onelist)
(define (howmanytrue tflist)
(apply + (map unless tflist zerolist onelist)))
Zerolist is an infinite list of zeros; onelist is an infinite list
of ones.
We make use of the fact that MAP's end test is that its
first argument is empty, so MAP will return a list the same size as
the argument tflist.
For example, if tflist is
(#t #t #f #t)
then map will return
(1 1 0 1)
created, in effect, this way:
(list (unless #t 0 1)
(unless #t 0 1)
(unless #f 0 1)
(unless #t 0 1))
And so + will return 3, the number of trues in the list.
4.28
Why force the operator of a combination?
Thunks are made by APPLY, representing arguments to defined procedures.
So we need a case in which the operator of an expression is the returned
argument of a defined procedure.
Here's an example:
(((lambda (a b) a) + ) 2 3)
4.30
Side effects vs. lazy evaluation
(a) Why is Ben right about foreach?
This is the end of the preview.
Sign up
to
access the rest of the document.
 Spring '08
 Harvey
 ObjectOriented Programming, Grammatical number, Predicate, Lazy evaluation

Click to edit the document details