about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14')
-rw-r--r--js/games/nluqo.github.io/~bh/61a-pages/Solutions/week141404
1 files changed, 1404 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14 b/js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14
new file mode 100644
index 0000000..53486bd
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/61a-pages/Solutions/week14
@@ -0,0 +1,1404 @@
+CS61A	Week 11 solutions
+
+LAB:
+----
+
+4.27  Lazy vs. mutation
+
+The first time you type COUNT you get 1; the second time you get 2.
+Why?  When you say
+	(define w (id (id 10)))
+the DEFINE special form handler eval-definition EVALs its second
+argument (id (id 10)).  Given an application, EVAL calls APPLY
+to invoke ID for the outer invocation, but the inner invocation
+is providing an argument to a compound procedure, so it's delayed.
+That's why COUNT is 1 -- the outer call to ID has actually happened,
+but not the inner one.
+
+The value of W is therefore a promise to compute (id 10), since
+ID returns its argument.  When you ask the evaluator to print W,
+that promise is fulfilled, and so COUNT becomes 2.
+
+
+4.29  Memoizing or not
+
+You'd expect a program that uses the same argument repeatedly to
+be most strongly affected.  For example, I wrote
+
+(define (n-copies n stuff)
+  (if (= n 0)
+      '()
+      (cons stuff (n-copies (- n 1) stuff))))
+
+Then if you use n-copies with something requiring a fair amount
+of computation, such as
+
+(n-copies 6 (factorial 7))
+
+you can see a dramatic difference.
+
+About their square/id example, remember to (set! count 0) before
+each experiment.  Then the memoizing version leaves count at 1,
+whereas the non-memoizing version sets count to 2.
+
+
+
+4.35 an-integer-between
+
+(define (an-integer-between low high)
+  (if (> low high)
+      (amb)
+      (amb low (an-integer-between (+ low 1) high))))
+
+
+4.38 adjacent floors
+
+Remove the line (require (not (= (abs (- smith fletcher)) 1)))
+
+
+[The continuation part of the lab was just try-this.]
+
+
+
+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)
+  (make-if (unless-predicate exp)
+	   (unless-consequent exp)
+	   (unless-alternative exp)))
+
+(define unless-predicate cadr)
+(define unless-alternative caddr)
+(define unless-consequent cadddr)
+
+Notice that we reversed the order of the last two subexpressions in
+the call to make-if.
+
+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 higher-order 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 (all-true? tf-list)
+  (accumulate and tf-list))
+
+Now, here's the strained example using UNLESS:  Suppose we have a list of
+true-false values and we'd like to add up the number of true ones.  Here's a
+somewhat strange way to do it:
+
+(define zero-list (cons 0 '()))
+(set-cdr! zero-list zero-list)
+
+(define one-list (cons 1 '()))
+(set-cdr! one-list one-list)
+
+(define (howmany-true tf-list)
+  (apply + (map unless tf-list zero-list one-list)))
+
+Zero-list is an infinite list of zeros; one-list 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 tf-list.  For example, if tf-list 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 for-each?
+
+For-each includes the expression (proc (car items)).  As we
+discussed in ex. 4.28, the lazy evaluator will force the
+operator of that expression, i.e., PROC.  The resulting
+procedure has two invocations of primitives, NEWLINE and
+DISPLAY.  Evaluating those invocations will actually call
+the procedures, and the argument X to DISPLAY will be
+evaluated because DISPLAY is primitive.
+
+(b) What happens in Cy's example?
+
+First of all, in ordinary Scheme both (p1 1) and (p2 1) give
+the result (1 2).
+
+With the book's version of eval-sequence, (p1 1) is still (1 2)
+but (p2 1) is 1, because the SET! will never happen.  The
+subprocedure P has a two-expression sequence as its body, and
+the first expression will never be evaluated.
+
+With Cy's version both (p1 1) and (p2 1) are (1 2), as in
+ordinary Scheme.
+
+(c) Why doesn't Cy's version change part (a)?
+
+The change isn't as dramatic as it may seem.  Don't think that
+the original eval-sequence calls delay-it!  It calls EVAL, and
+most of the time EVAL does return a value, not a thunk.  In
+particular, a procedure call is carried out right away; it's
+only the *arguments* to the procedure that are delayed.  That's
+why Cy had to use a weird example in which a SET! expression
+is used as an argument to a procedure in order to get the wrong
+result.
+
+(d) What's the right thing to do?
+
+The combination of lazy evaluation and mutation in the same language
+is so confusing that programmers would be surprised no matter which
+choice we made.  That's why, in the real world, the languages that
+use normal order evaluation are *functional* languages in which
+there is no mutation or other side effects.  In such a language,
+there are no sequences (if there are no side effects, what would
+be the point?) and the problem doesn't arise.
+
+But if we really wanted to have a normal-order Scheme, we'd
+probably want to change the semantics of the language as little
+as possible -- programs that work in ordinary Scheme should work
+in lazy Scheme too.  So I think Cy is right.
+
+
+4.32  Lazy trees
+
+One possibility is to use doubly-lazy lists as an alternative to
+interleaving, when dealing with a naturally two-dimensional problem.
+For example, to get pairs of integers, we could say
+
+(define (pairs a b)
+  (cons (map (lambda (x) (cons (car a) x)) b)
+	(pairs (cdr a) b)))
+
+Then we could use this data structure with two-dimensional versions
+of the usual higher order procedures.  For example:
+
+(define (2dfilter pred s)
+  (if (null? s)
+      '()
+      (cons (filter pred (car s))
+	    (2dfilter pred (cdr s)))))
+
+
+4.33  Quoted lazy lists
+
+Instead of
+        ((quoted? exp) (text-of-quotation exp))
+we need a more complicated treatment to turn the ordinary lists
+of the underlying Scheme into lazy lists.
+
+        ((quoted? exp) (process-quotation (text-of-quotation exp) env))
+
+(define (process-quotation quoted env)
+  (if (pair? quoted)
+      (lazy-cons (process-quotation (car quoted) env)
+		 (process-quotation (cdr quoted) env)
+		 env)
+      quoted))
+
+(define (lazy-cons x y env)
+  (make-procedure '(m) (list (list 'm x y)) env))
+
+or alternatively
+
+(define (lazy-cons x y env)
+  (apply (lookup-variable-value 'cons env)
+	 (list x y)))
+
+This lazy-cons is the below-the-line equivalent of the above-the-line
+CONS on page 409.
+
+
+
+4.36 all Pythagorean triples
+
+Replacing an-integer-between with an-integer-starting-from won't
+work because the AMB that provides the value for K will never fail,
+and so I and J will always be 1 forever.
+
+To make this work, we note that K must always be larger than I or J,
+so I and J can be restricted to finite ranges if we choose a value
+for K first:
+
+(define (a-pythgorean-triple)
+  (let ((k (an-integer-starting-from 1)))
+    (let ((i (an-integer-between 1 (- k 1))))
+      (let ((j (an-integer-between i (- k 1))))
+	(require (= (+ (* i i) (* j j)) (* k k)))
+	(list i j k)))))
+
+
+4.42 liars
+
+(define (liars)
+  (define (onetrue? x y)
+    (if x (if y #f #t) y))
+  (let ((betty (amb 1 2 3 4 5))
+	(ethel (amb 1 2 3 4 5))
+	(joan (amb 1 2 3 4 5))
+	(kitty (amb 1 2 3 4 5))
+	(mary (amb 1 2 3 4 5)))
+    (require (distinct? (list betty ethel joan kitty mary)))
+    (require (onetrue? (= kitty 2) (= betty 3)))
+    (require (onetrue? (= ethel 1) (= joan 2)))
+    (require (onetrue? (= joan 3) (= ethel 5)))
+    (require (onetrue? (= kitty 2) (= mary 4)))
+    (require (onetrue? (= mary 4) (= betty 1)))
+    (list (list 'betty betty) (list 'ethel ethel) (list 'joan joan)
+	  (list 'kitty kitty) (list 'mary mary))))
+
+As in the multiple dwelling puzzle, this program can be made much more
+efficient by checking for distinct values as we go along instead of
+after all values have been assigned:
+
+(let ((betty (amb 1 2 3 4 5))
+      (ethel (amb 1 2 3 4 5)))
+  (require (distinct? (list betty ethel)))
+  (let ((joan (amb 1 2 3 4 5)))
+    (require (distinct? (list betty ethel joan)))
+    ...
+
+
+4.45 ambiguous sentence
+
+(sentence
+ (simple-noun-phrase (article the) (noun professor))
+ (verb-phrase
+  (verb lectures)
+  (prep-phrase (prep to)
+	       (noun-phrase
+		(simple-noun-phrase (article the) (noun student))
+		(prep-phrase (prep in)
+			     (noun-phrase
+			      (simple-noun-phrase (article the) (noun class))
+			      (prep-phrase (prep with)
+					   (simple-noun-phrase (article the)
+							       (noun cat)))))))))
+
+This version means that a cat is a student in the class, and the professor
+lectures to another student in the class.
+
+(sentence
+ (simple-noun-phrase (article the) (noun professor))
+ (verb-phrase
+  (verb lectures)
+  (prep-phrase (prep to)
+	       (noun-phrase
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun student))
+		 (prep-phrase (prep in)
+			      (simple-noun-phrase (article the) (noun class))))
+		(prep-phrase (prep with)
+			     (simple-noun-phrase (article the)
+						 (noun cat)))))))
+
+This version means that the professor lectures to a student, and that that
+student is in the class and has a cat, which may or may not be present.
+
+(sentence
+ (simple-noun-phrase (article the) (noun professor))
+ (verb-phrase
+  (verb-phrase
+   (verb lectures)
+   (prep-phrase (prep to)
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun student))
+		 (prep-phrase (prep in)
+			      (simple-noun-phrase (article the) (noun class))))))
+  (prep-phrase (prep with)
+	       (simple-noun-phrase (article the)
+				   (noun cat)))))
+
+This version means that the professor brings a cat along while lecturing
+to the student who is in the class.
+
+(sentence
+ (simple-noun-phrase (article the) (noun professor))
+ (verb-phrase
+  (verb-phrase
+   (verb-phrase
+    (verb lectures)
+    (prep-phrase (prep to)
+		 (noun-phrase
+		  (simple-noun-phrase (article the) (noun student)))))
+   (prep-phrase (prep in)
+		(simple-noun-phrase (article the) (noun class))))
+  (prep-phrase (prep with)
+	       (simple-noun-phrase (article the)
+				   (noun cat)))))
+
+This version means that the professor does the lecturing in the class,
+bringing a cat along, to some student about whom we know nothing.
+
+(sentence
+ (simple-noun-phrase (article the) (noun professor))
+ (verb-phrase
+  (verb-phrase
+   (verb lectures)
+   (prep-phrase (prep to)
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun student)))))
+  (prep-phrase (prep in)
+	       (noun-phrase
+		(simple-noun-phrase (article the) (noun class))
+		(prep-phrase (prep with)
+			     (simple-noun-phrase (article the)
+						 (noun cat)))))))
+
+This version means that the professor does the lecturing in a class
+that includes a cat as a member, to a student about whom we know nothing.
+
+
+4.47 left-recursive grammar
+
+As Louis' programs go, this one is pretty successful!  It does generate
+the two correct parsings for "The professor lectures to the student
+with the cat," in the opposite order from what's shown in the book.
+But if you say try-again again, instead of reporting that there are
+no more values, the parser gets in an infinite loop.
+
+What happens is this:  (parse-word verbs) fails, so parse-verb-phrase
+is called recursively.  In that recursive call, (parse-word verbs) fails,
+so parse-verb-phrase is called recursively.  In that recursive call...
+and so on.
+
+Interchanging the order of expressions in the AMB just makes things
+worse; this infinite recursion happens the *first* time, so you don't
+even see the correct parsings before it loops.
+
+
+4.48 grammar extensions
+
+For compound sentences, first rename parse-sentence as parse-simple-sentence:
+
+(define (parse-simple-sentence)
+  (list 'simple-sentence
+	(parse-noun-phrase)
+	(parse-verb-phrase)))
+
+(define (parse-sentence)
+  (define (maybe-extend sentence)
+    (amb sentence
+	 (maybe-extend (list 'sentence
+			     sentence
+			     (parse-word connectors)
+			     (parse-simple-sentence)))))
+  (maybe-extend (parse-simple-sentence)))
+
+(define connectors '(connector and or but))
+
+For adjectives, we have to provide for the possibility of them
+between the article and the noun:
+
+(define (parse-simple-noun-phrase)
+  (cons 'simple-noun-phrase
+	(append (list (parse-word articles))
+		(maybe-some adjectives)
+		(list (parse-word nouns)))))
+
+(define adjectives '(adjective big tiny silly robust enthusiastic))
+
+(define (maybe-some words)
+  (amb (cons (parse-word words)
+	     (maybe-some words))
+       '()))
+
+Note that unlike most of the parsing procedures, maybe-some doesn't fail if
+it can't find what it wants.  If it can't find any adjectives it just
+returns an empty list.  That's why parse-simple-noun-phrase has to use
+append, to avoid seeing
+
+    (simple-noun-phrase (article the) () (noun cat))
+
+Adverbs are similar except that they go into parse-verb-phrase.
+
+
+4.49  generating sentences
+
+(define (parse-word word-list)
+  (define (iter words)
+    (if (null? words)
+	(amb)
+	(amb (car words) (iter (cdr words)))))
+  (list (car word-list) (iter (cdr word-list))))
+
+Here are the first several sentences it creates:
+(sentence (noun-phrase (article the) (noun student)) (verb studies))
+(sentence (noun-phrase (article the) (noun student)) (verb lectures))
+(sentence (noun-phrase (article the) (noun student)) (verb eats))
+(sentence (noun-phrase (article the) (noun student)) (verb sleeps))
+(sentence (noun-phrase (article the) (noun professor)) (verb studies))
+(sentence (noun-phrase (article the) (noun professor)) (verb lectures))
+(sentence (noun-phrase (article the) (noun professor)) (verb eats))
+(sentence (noun-phrase (article the) (noun professor)) (verb sleeps))
+(sentence (noun-phrase (article the) (noun cat)) (verb studies))
+
+
+4.50  random choice
+
+We must write ANALYZE-RAMB, a variant on the ANALYZE-AMB of p. 434:
+
+(define (analyze-ramb exp)
+  (let ((cprocs (map analyze (amb-choices exp))))
+    (lambda (env succeed fail)
+      (define (try-next choices)
+	(if (null? choices)
+	    (fail)
+	    (let ((random-order (rotate choices (random (length choices)))))
+	      ((car random-order) env
+	                          succeed
+	                          (lambda ()
+				    (try-next (cdr random-order)))))))
+      (try-next cprocs))))
+
+(define (rotate seq num)
+  (if (= num 0)
+      seq
+      (rotate (append (cdr seq) (list (car seq)))
+	      (- num 1)))
+
+Then we must add a clause to ANALYZE to check for and handle RAMB,
+similar to the one for AMB.
+
+
+It's not actually so easy to use RAMB to get good sentences.  The problem
+is that we really don't want a more complicated choice to be just as likely
+as a simple choice, or our sentences will be too long.  If we change
+every AMB in the parser to RAMB, I get these results:
+
+[Note: The second one is really long!  I suggest reading this in emacs
+and using control-meta-F to skip over it.]
+
+(sentence
+ (noun-phrase
+  (simple-noun-phrase (article the) (noun professor))
+  (prep-phrase (prep with)
+	       (noun-phrase
+		(simple-noun-phrase (article a) (noun cat))
+		(prep-phrase (prep for)
+			     (simple-noun-phrase (article a) (noun student))))))
+ (verb studies))
+
+(sentence
+ (noun-phrase
+  (simple-noun-phrase (article the) (noun professor))
+  (prep-phrase (prep with)
+	       (noun-phrase
+		(simple-noun-phrase (article a) (noun cat))
+		(prep-phrase (prep for)
+			     (simple-noun-phrase (article a)
+						 (noun student))))))
+ (verb-phrase
+  (verb-phrase
+   (verb studies)
+   (prep-phrase
+    (prep to)
+    (noun-phrase
+     (noun-phrase
+      (noun-phrase
+       (noun-phrase
+	(simple-noun-phrase (article the) (noun professor))
+	(prep-phrase
+	 (prep in)
+	 (noun-phrase
+	  (noun-phrase
+	   (noun-phrase
+	    (simple-noun-phrase (article the) (noun professor))
+	    (prep-phrase
+	     (prep by)
+	     (noun-phrase
+	      (simple-noun-phrase (article a) (noun class))
+	      (prep-phrase
+	       (prep with)
+	       (noun-phrase
+		(noun-phrase
+		 (simple-noun-phrase (article a) (noun student))
+		 (prep-phrase
+		  (prep to)
+		  (simple-noun-phrase (article the) (noun student))))
+		(prep-phrase
+		 (prep for)
+		 (noun-phrase
+		  (noun-phrase
+		   (simple-noun-phrase (article the) (noun class))
+		   (prep-phrase
+		    (prep for)
+		    (noun-phrase
+		     (simple-noun-phrase (article a) (noun student))
+		     (prep-phrase
+		      (prep with)
+		      (simple-noun-phrase (article the) (noun professor))))))
+		  (prep-phrase
+		   (prep for)
+		   (noun-phrase
+		    (noun-phrase
+		     (noun-phrase
+		      (simple-noun-phrase (article the) (noun professor))
+		      (prep-phrase
+		       (prep for)
+		       (simple-noun-phrase (article the) (noun student))))
+		     (prep-phrase
+		      (prep for)
+		      (noun-phrase
+		       (simple-noun-phrase (article the) (noun class))
+		       (prep-phrase
+			(prep to)
+			(simple-noun-phrase (article a) (noun professor))))))
+		    (prep-phrase
+		     (prep to)
+		     (noun-phrase
+		      (simple-noun-phrase (article the) (noun student))
+		      (prep-phrase
+		       (prep to)
+		       (noun-phrase
+			(simple-noun-phrase (article a) (noun professor))
+			(prep-phrase
+			 (prep for)
+			 (simple-noun-phrase (article a)
+					     (noun student))))))))))))))))
+	   (prep-phrase
+	    (prep for)
+	    (simple-noun-phrase (article the) (noun student))))
+	  (prep-phrase
+	   (prep with)
+	   (noun-phrase
+	    (simple-noun-phrase (article a) (noun student))
+	    (prep-phrase
+	     (prep to)
+	     (noun-phrase
+	      (noun-phrase
+	       (noun-phrase
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun student))
+		 (prep-phrase
+		  (prep in)
+		  (simple-noun-phrase (article the) (noun cat))))
+		(prep-phrase
+		 (prep for)
+		 (noun-phrase
+		  (noun-phrase
+		   (noun-phrase
+		    (simple-noun-phrase (article the) (noun student))
+		    (prep-phrase
+		     (prep with)
+		     (noun-phrase
+		      (simple-noun-phrase (article a) (noun student))
+		      (prep-phrase
+		       (prep for)
+		       (noun-phrase
+			(noun-phrase
+			 (simple-noun-phrase (article a) (noun professor))
+			 (prep-phrase
+			  (prep for)
+			  (noun-phrase
+			   (noun-phrase
+			    (simple-noun-phrase (article a) (noun professor))
+			    (prep-phrase
+			     (prep for)
+			     (simple-noun-phrase (article the)
+						 (noun student))))
+			   (prep-phrase
+			    (prep with)
+			    (simple-noun-phrase (article a)
+						(noun professor))))))
+			(prep-phrase
+			 (prep to)
+			 (noun-phrase
+			  (noun-phrase
+			   (simple-noun-phrase (article the) (noun student))
+			   (prep-phrase
+			    (prep with)
+			    (noun-phrase
+			     (simple-noun-phrase (article a) (noun student))
+			     (prep-phrase
+			      (prep to)
+			      (simple-noun-phrase (article the)
+						  (noun class))))))
+			  (prep-phrase
+			   (prep for)
+			   (simple-noun-phrase (article the)
+					       (noun student))))))))))
+		   (prep-phrase
+		    (prep for)
+		    (noun-phrase
+		     (simple-noun-phrase (article a) (noun professor))
+		     (prep-phrase
+		      (prep with)
+		      (noun-phrase
+		       (simple-noun-phrase (article a) (noun professor))
+		       (prep-phrase
+			(prep for)
+			(simple-noun-phrase (article the) (noun student))))))))
+		  (prep-phrase
+		   (prep for)
+		   (simple-noun-phrase (article the) (noun class))))))
+	       (prep-phrase
+		(prep to)
+		(simple-noun-phrase (article the) (noun class))))
+	      (prep-phrase
+	       (prep in)
+	       (simple-noun-phrase (article a) (noun student))))))))))
+       (prep-phrase
+	(prep to)
+	(noun-phrase
+	 (noun-phrase
+	  (noun-phrase
+	   (simple-noun-phrase (article the) (noun professor))
+	   (prep-phrase
+	    (prep for)
+	    (noun-phrase
+	     (noun-phrase
+	      (simple-noun-phrase (article the) (noun student))
+	      (prep-phrase
+	       (prep in)
+	       (simple-noun-phrase (article a) (noun student))))
+	     (prep-phrase
+	      (prep with)
+	      (noun-phrase
+	       (simple-noun-phrase (article a) (noun class))
+	       (prep-phrase
+		(prep to)
+		(simple-noun-phrase (article a) (noun professor))))))))
+	  (prep-phrase
+	   (prep in)
+	   (noun-phrase
+	    (simple-noun-phrase (article the) (noun professor))
+	    (prep-phrase
+	     (prep for)
+	     (noun-phrase
+	      (noun-phrase
+	       (noun-phrase
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun professor))
+		 (prep-phrase
+		  (prep for)
+		  (simple-noun-phrase (article the) (noun student))))
+		(prep-phrase
+		 (prep for)
+		 (noun-phrase
+		  (noun-phrase
+		   (noun-phrase
+		    (simple-noun-phrase (article the) (noun professor))
+		    (prep-phrase
+		     (prep to)
+		     (noun-phrase
+		      (simple-noun-phrase (article a) (noun student))
+		      (prep-phrase
+		       (prep for)
+		       (noun-phrase
+			(simple-noun-phrase (article a) (noun student))
+			(prep-phrase
+			 (prep for)
+			 (simple-noun-phrase (article a) (noun student))))))))
+		   (prep-phrase
+		    (prep for)
+		    (noun-phrase
+		     (simple-noun-phrase (article the) (noun student))
+		     (prep-phrase
+		      (prep for)
+		      (simple-noun-phrase (article a) (noun professor))))))
+		  (prep-phrase
+		   (prep to)
+		   (noun-phrase
+		    (simple-noun-phrase (article a) (noun professor))
+		    (prep-phrase
+		     (prep for)
+		     (noun-phrase
+		      (simple-noun-phrase (article the) (noun student))
+		      (prep-phrase
+		       (prep in)
+		       (noun-phrase
+			(simple-noun-phrase (article the) (noun student))
+			(prep-phrase
+			 (prep in)
+			 (noun-phrase
+			  (simple-noun-phrase (article the) (noun professor))
+			  (prep-phrase
+			   (prep to)
+			   (noun-phrase
+			    (simple-noun-phrase (article the) (noun class))
+			    (prep-phrase
+			     (prep in)
+			     (noun-phrase
+			      (simple-noun-phrase (article the)
+						  (noun professor))
+			      (prep-phrase
+			       (prep to)
+			       (simple-noun-phrase
+				(article a)
+				(noun class))))))))))))))))))
+	       (prep-phrase
+		(prep for)
+		(noun-phrase
+		 (simple-noun-phrase (article a) (noun cat))
+		 (prep-phrase
+		  (prep to)
+		  (simple-noun-phrase (article a) (noun student))))))
+	      (prep-phrase
+	       (prep to)
+	       (simple-noun-phrase (article a) (noun class))))))))
+	 (prep-phrase
+	  (prep for)
+	  (simple-noun-phrase (article a) (noun professor))))))
+      (prep-phrase
+       (prep to)
+       (noun-phrase
+	(noun-phrase
+	 (noun-phrase
+	  (noun-phrase
+	   (simple-noun-phrase (article the) (noun class))
+	   (prep-phrase
+	    (prep by)
+	    (noun-phrase
+	     (noun-phrase
+	      (noun-phrase
+	       (noun-phrase
+		(noun-phrase
+		 (simple-noun-phrase (article the) (noun professor))
+		 (prep-phrase
+		  (prep to)
+		  (simple-noun-phrase (article the) (noun student))))
+		(prep-phrase
+		 (prep for)
+		 (simple-noun-phrase (article the) (noun professor))))
+	       (prep-phrase
+		(prep for)
+		(simple-noun-phrase (article the) (noun student))))
+	      (prep-phrase
+	       (prep in)
+	       (simple-noun-phrase (article the) (noun professor))))
+	(prep-phrase
+	 (prep for)
+	 (simple-noun-phrase (article a) (noun student))))))
+	  (prep-phrase
+	   (prep to)
+	   (simple-noun-phrase (article a) (noun student))))
+	 (prep-phrase
+	  (prep in)
+	  (noun-phrase
+	   (simple-noun-phrase (article a) (noun student))
+	   (prep-phrase
+	    (prep with)
+	    (noun-phrase
+	     (noun-phrase
+	      (simple-noun-phrase (article a) (noun class))
+	      (prep-phrase
+	       (prep for)
+	       (simple-noun-phrase (article a) (noun professor))))
+	     (prep-phrase
+	      (prep for)
+	      (noun-phrase
+	       (noun-phrase
+		(noun-phrase
+		 (noun-phrase
+		  (simple-noun-phrase (article the) (noun cat))
+		  (prep-phrase
+		   (prep for)
+		   (simple-noun-phrase (article a) (noun professor))))
+		 (prep-phrase
+		  (prep for)
+		  (noun-phrase
+		   (simple-noun-phrase (article the) (noun class))
+		   (prep-phrase
+		    (prep with)
+		    (noun-phrase
+		     (noun-phrase
+		      (simple-noun-phrase (article the) (noun professor))
+		      (prep-phrase
+		       (prep with)
+		       (simple-noun-phrase (article a) (noun student))))
+		     (prep-phrase
+		      (prep for)
+		      (noun-phrase
+		       (simple-noun-phrase (article the) (noun professor))
+		       (prep-phrase
+			(prep to)
+			(noun-phrase
+			 (simple-noun-phrase (article a) (noun student))
+			 (prep-phrase
+			  (prep to)
+			  (noun-phrase
+			   (noun-phrase
+			    (noun-phrase
+			     (simple-noun-phrase (article the) (noun student))
+			     (prep-phrase
+			      (prep to)
+			      (simple-noun-phrase (article a) (noun student))))
+			    (prep-phrase
+			     (prep to)
+			     (noun-phrase
+			      (simple-noun-phrase (article a) (noun student))
+			      (prep-phrase
+			       (prep to)
+			       (noun-phrase
+				(noun-phrase
+				 (noun-phrase
+				  (noun-phrase
+				   (simple-noun-phrase (article a)
+						       (noun student))
+				   (prep-phrase
+				    (prep for)
+				    (simple-noun-phrase (article the)
+							(noun student))))
+				  (prep-phrase
+				   (prep to)
+				   (simple-noun-phrase (article a)
+						       (noun class))))
+				 (prep-phrase
+				  (prep for)
+				  (noun-phrase
+				   (noun-phrase
+				    (simple-noun-phrase (article the)
+							(noun class))
+				    (prep-phrase
+				     (prep for)
+				     (simple-noun-phrase (article the)
+							 (noun class))))
+				   (prep-phrase
+				    (prep in)
+				    (noun-phrase
+				     (noun-phrase
+				      (simple-noun-phrase (article a)
+							  (noun professor))
+				      (prep-phrase
+				       (prep to)
+				       (noun-phrase
+					(simple-noun-phrase (article a)
+							    (noun student))
+					(prep-phrase
+					 (prep for)
+					 (simple-noun-phrase
+					  (article the)
+					  (noun student))))))
+				     (prep-phrase
+				      (prep by)
+				      (simple-noun-phrase (article a)
+							  (noun class))))))))
+				(prep-phrase
+				 (prep in)
+				 (noun-phrase
+				  (simple-noun-phrase (article the)
+						      (noun professor))
+				  (prep-phrase
+				   (prep to)
+				   (noun-phrase
+				    (simple-noun-phrase (article the)
+							(noun professor))
+				    (prep-phrase
+				     (prep for)
+				     (simple-noun-phrase
+				      (article the)
+				      (noun student))))))))))))
+			   (prep-phrase
+			    (prep with)
+			    (noun-phrase
+			     (noun-phrase
+			      (simple-noun-phrase (article a) (noun student))
+			      (prep-phrase
+			       (prep by)
+			       (simple-noun-phrase (article a)
+						   (noun student))))
+			     (prep-phrase
+			      (prep for)
+			      (noun-phrase
+			       (simple-noun-phrase (article the) (noun class))
+			       (prep-phrase
+				(prep to)
+				(simple-noun-phrase
+				 (article the)
+				 (noun professor))))))))))))))))))
+		(prep-phrase
+		 (prep to)
+		 (noun-phrase
+		  (noun-phrase
+		   (noun-phrase
+		    (noun-phrase
+		     (simple-noun-phrase (article a) (noun student))
+		     (prep-phrase
+		      (prep for)
+		      (simple-noun-phrase (article a) (noun class))))
+		    (prep-phrase
+		     (prep for)
+		     (noun-phrase
+		      (simple-noun-phrase (article the) (noun student))
+		      (prep-phrase
+		       (prep for)
+		       (simple-noun-phrase (article the) (noun student))))))
+		   (prep-phrase
+		    (prep to)
+		    (noun-phrase
+		     (noun-phrase
+		      (noun-phrase
+		       (noun-phrase
+			(simple-noun-phrase (article the) (noun student))
+			(prep-phrase
+			 (prep for)
+			 (noun-phrase
+			  (noun-phrase
+			   (noun-phrase
+			    (simple-noun-phrase (article a) (noun student))
+			    (prep-phrase
+			     (prep for)
+			     (simple-noun-phrase (article the)
+						 (noun student))))
+			   (prep-phrase
+			    (prep to)
+			    (noun-phrase
+			     (noun-phrase
+			      (simple-noun-phrase (article the)
+						  (noun professor))
+			      (prep-phrase
+			       (prep for)
+			       (noun-phrase
+				(simple-noun-phrase (article a) (noun student))
+				(prep-phrase
+				 (prep by)
+				 (noun-phrase
+				  (simple-noun-phrase (article a)
+						      (noun student))
+				  (prep-phrase
+				   (prep in)
+				   (noun-phrase
+				    (noun-phrase
+				     (simple-noun-phrase (article a)
+							 (noun student))
+				     (prep-phrase
+				      (prep to)
+				      (noun-phrase
+				       (simple-noun-phrase (article the)
+							   (noun student))
+				       (prep-phrase
+					(prep for)
+					(simple-noun-phrase
+					 (article a)
+					 (noun professor))))))
+				    (prep-phrase
+				     (prep to)
+				     (simple-noun-phrase (article a)
+							 (noun cat))))))))))
+			     (prep-phrase
+			      (prep for)
+			      (noun-phrase
+			       (simple-noun-phrase (article a)
+						   (noun professor))
+			       (prep-phrase
+				(prep for)
+				(simple-noun-phrase (article the)
+						    (noun student))))))))
+			  (prep-phrase
+			   (prep for)
+			   (noun-phrase
+			    (noun-phrase
+			     (simple-noun-phrase (article a) (noun cat))
+			     (prep-phrase
+			      (prep for)
+			      (simple-noun-phrase (article the)
+						  (noun professor))))
+			    (prep-phrase
+			     (prep by)
+			     (simple-noun-phrase (article a)
+						 (noun professor))))))))
+		       (prep-phrase
+			(prep for)
+			(noun-phrase
+			 (simple-noun-phrase (article the) (noun cat))
+			 (prep-phrase
+			  (prep for)
+			  (noun-phrase
+			   (simple-noun-phrase (article a) (noun professor))
+			   (prep-phrase
+			    (prep with)
+			    (simple-noun-phrase (article the) (noun cat))))))))
+		      (prep-phrase
+		       (prep in)
+		       (noun-phrase
+			(simple-noun-phrase (article the) (noun professor))
+			(prep-phrase
+			 (prep for)
+			 (simple-noun-phrase (article a) (noun cat))))))
+		     (prep-phrase
+		      (prep for)
+		      (simple-noun-phrase (article the) (noun student))))))
+		  (prep-phrase
+		   (prep in)
+		   (noun-phrase
+		    (simple-noun-phrase (article the) (noun class))
+		    (prep-phrase
+		     (prep for)
+		     (simple-noun-phrase (article the) (noun professor))))))))
+	       (prep-phrase
+		(prep to)
+		(noun-phrase
+		 (simple-noun-phrase (article a) (noun student))
+		 (prep-phrase
+		  (prep for)
+		  (simple-noun-phrase (article the) (noun student))))))))))))
+	(prep-phrase
+	 (prep with)
+	 (simple-noun-phrase (article a) (noun student))))))
+     (prep-phrase
+      (prep for)
+      (noun-phrase
+       (simple-noun-phrase (article the) (noun professor))
+       (prep-phrase
+	(prep in)
+	(noun-phrase
+	 (simple-noun-phrase (article the) (noun class))
+	 (prep-phrase
+	  (prep to)
+	  (simple-noun-phrase (article a) (noun student))))))))))
+  (prep-phrase
+   (prep to)
+   (noun-phrase
+    (noun-phrase
+     (simple-noun-phrase (article the) (noun cat))
+     (prep-phrase
+      (prep for)
+      (noun-phrase
+       (noun-phrase
+	(simple-noun-phrase (article the) (noun student))
+	(prep-phrase
+	 (prep for)
+	 (simple-noun-phrase (article the) (noun professor))))
+       (prep-phrase
+	(prep for)
+	(simple-noun-phrase (article a) (noun student))))))
+    (prep-phrase
+     (prep in)
+     (simple-noun-phrase (article a) (noun student)))))))
+
+We can improve on this by making the addition of a prepositional
+phrase less likely.  For example, we could rewrite PARSE-NOUN-PHRASE
+and PARSE-VERB-PHRASE this way:
+
+(define (parse-noun-phrase)
+  (define (maybe-extend noun-phrase)
+    (ramb noun-phrase
+	  noun-phrase
+	  noun-phrase
+	  noun-phrase
+	  noun-phrase
+         (maybe-extend (list 'noun-phrase
+                             noun-phrase
+                             (parse-prepositional-phrase)))))
+  (maybe-extend (parse-simple-noun-phrase)))
+
+(define (parse-verb-phrase)
+  (define (maybe-extend verb-phrase)
+    (ramb verb-phrase
+	  verb-phrase
+	  verb-phrase
+	  verb-phrase
+	  verb-phrase
+         (maybe-extend (list 'verb-phrase
+                             verb-phrase
+                             (parse-prepositional-phrase)))))
+  (maybe-extend (parse-word verbs)))
+
+With these changes, here are the first few sentences I get:
+
+(sentence (simple-noun-phrase (article a) (noun professor)) (verb sleeps))
+
+(sentence (simple-noun-phrase (article a) (noun professor)) (verb sleeps))
+
+(sentence (simple-noun-phrase (article a) (noun professor))
+	  (verb-phrase
+	   (verb sleeps)
+	   (prep-phrase (prep for)
+			(simple-noun-phrase (article a) (noun student)))))
+
+(sentence
+ (simple-noun-phrase (article a) (noun professor))
+ (verb-phrase (verb sleeps)
+	      (prep-phrase (prep for)
+			   (simple-noun-phrase (article a) (noun student)))))
+
+This is still not quite what we want, but with more fine tuning we can
+probably get to a reasonable sentence generator.
+
+
+4.52  if-fail
+
+To add a new special form we add a clause to ANALYZE, which should call
+this new procedure:
+
+(define (analyze-if-fail exp)
+  (let ((trial (analyze (if-fail-trial exp)))
+	(failure (analyze (if-fail-failure exp))))
+    (lambda (env succeed fail)
+      (trial env
+	     succeed
+	     (lambda () (failure env succeed fail))))))
+
+(define if-fail-trial cadr)
+(define if-fail-failure caddr)
+
+Here's a version to go with vambeval, the ambeval without analysis:
+
+(define (eval-if-fail exp env succeed fail)
+  (vambeval (if-fail-trial exp)
+	    env
+	    succeed
+	    (lambda () (vambeval (if-fail-failure exp)
+				 env
+				 succeed
+				 fail))))
+
+
+Extra for Experts
+=================
+
+4.31
+
+Despite what the exercise says, there's no need to change the procedures that
+determine the DEFINE syntax, because it doesn't check that the formal
+parameters are symbols.  Even MAKE-PROCEDURE doesn't check.
+
+The hard part is in procedure invocation.  The original metacircular evaluator
+has this in the big COND in EVAL:
+
+	((application? exp)
+	 (mc-apply (MC-EVAL (operator exp) env)
+		   (LIST-OF-VALUES (operands exp) env)))
+
+The lazy evaluator in the book changes that to
+
+        ((application? exp)
+         (mc-apply (ACTUAL-VALUE (operator exp) env)
+		   (operands exp)	; no LIST-OF-VALUES
+		   ENV))		; added argument
+
+(For this exercise, it's easier to work with the book's version than with
+the slightly different alternative shown in the lecture notes.)
+
+So now we're giving APPLY expressions rather than values, and we're also
+giving APPLY an environment in which to evaluate or thunkify the values.
+We don't have to make any change to the book's EVAL; the hard part is in
+APPLY, in which we have to decide whether to evaluate or thunkify.
+
+Here's the book's lazy APPLY:
+
+(define (mc-apply procedure arguments env)
+  (cond ((primitive-procedure? procedure)
+         (apply-primitive-procedure
+          procedure
+          (LIST-OF-ARG-VALUES ARGUMENTS ENV)))	; ***
+        ((compound-procedure? procedure)
+         (eval-sequence
+          (procedure-body procedure)
+          (extend-environment
+           (procedure-parameters procedure)
+           (LIST-OF-DELAYED-ARGS ARGUMENTS ENV) ; ***
+           (procedure-environment procedure))))
+        (else
+         (error
+          "Unknown procedure type -- APPLY" procedure))))
+
+The two commented lines handle evaluation, for primitive procedures, and
+thunking, for non-primitive procedures.  It's the latter we have to change;
+the args may be evaluated, thunked with memoization, or thunked without
+memoization.  To make this decision, we have to look at the formal parameters
+of the procedure we're calling.  So the second commented line above will
+change to
+
+           (PROCESS-ARGS arguments (PROCEDURE-PARAMETERS PROCEDURE) env)
+
+Two things have changed; we're calling a not-yet-written procedure
+PROCESS-ARGS instead of LIST-OF-DELAYED-ARGS, and we're giving that procedure
+the formal parameters as well as the actual argument expressions.
+
+One more thing has to change in APPLY:  Since the list returned by
+PROCEDURE-PARAMETERS is no longer a list of symbols, but can now include
+sublists such as (B LAZY), we have to extract the real formal parameter
+names from it.  So the final version of APPLY is this:
+
+(define (mc-apply procedure arguments env)
+  (cond ((primitive-procedure? procedure)
+         (apply-primitive-procedure
+          procedure
+          (list-of-arg-values arguments env)))
+        ((compound-procedure? procedure)
+         (eval-sequence
+          (procedure-body procedure)
+          (extend-environment
+           (EXTRACT-NAMES (procedure-parameters procedure))		 ; ***
+           (PROCESS-ARGS arguments (PROCEDURE-PARAMETERS PROCEDURE) env) ; ***
+           (procedure-environment procedure))))
+        (else
+         (error
+          "Unknown procedure type -- APPLY" procedure))))
+
+Now comes the actual work, in EXTRACT-NAMES and in PROCESS-ARGS.
+
+EXTRACT-NAMES takes as its argument a list such as
+	(A (B LAZY) C (D LAZY-MEMO))
+and returns a list with just the variable names:
+	(A B C D)
+
+(define (extract-names formals)
+  (cond ((null? formals) '())
+	((pair? (car formals))	; CAR is (VAR TYPE), so keep CAAR in result
+	 (cons (caar formals) (extract-names (cdr formals))))
+	(else (cons (car formals) (extract-names (cdr formals))))))
+
+PROCESS-ARGS takes an argument list, let's say
+	((+ 2 3) (- 4 5) (* 6 7) (/ 8 9))
+and a parameter list, such as
+	(A (B LAZY) C (D LAZY-MEMO))
+and matches them up.  It pays no attention to the variable names in the
+parameter list; it's only looking for LAZY or LAZY-MEMO type tags.  It returns
+a list of argument values-and-thunks:
+	(5 (THUNK-NOMEMO (- 4 5) <env>) 42 (THUNK-MEMO (/ 8 9) <env>))
+where <env> represents an actual environment, not the word ENV.  The argument
+expressions (+ 2 3) and (* 6 7) correspond to non-lazy parameters A and C,
+so they've been evaluated; the other arguments have been turned into thunks
+by combining them with a type-tag (THUNK-NOMEMO or THUNK-MEMO as appropriate)
+and an environment.  Instead of the book's DELAY-IT procedure we have to use
+two different procedures, DELAY-NOMEMO and DELAY-MEMO, to construct the thunks.
+
+(define (process-args args formals env)
+  (cond ((null? args) '())
+	((null? formals)
+	 (error "Too many arguments"))
+	((pair? (car formals))
+	 (cond ((eq? (cadar formals) 'lazy)
+		(cons (delay-nomemo (car args) env)
+		      (process-args (cdr args) (cdr formals) env)))
+	       ((eq? (cadar formals) 'lazy-memo)
+		(cons (delay-memo (car args) env)
+		      (process-args (cdr args) (cdr formals) env)))
+	       (else (error "Unrecognized parameter type" (cadar formals)))))
+	(else (cons (EVAL (car args))
+		    (process-args (cdr args) (cdr formals) env)))))
+
+Note the call to EVAL in capital letters two lines up.  Should that be EVAL
+or ACTUAL-VALUE?  The issue is what behavior we want when a procedure with a
+non-lazy parameter is called with a thunk (created by calling some other
+non-primitive procedure) as the argument:
+
+	(define (foo x)
+	  x)
+
+	(define (baz (lazy x))
+	  x)
+
+	(define p (foo (baz (/ 1 0))))
+
+What should happen?  FOO's argument is non-lazy, so we evaluate the argument
+expression (BAZ (/ 1 0)).  BAZ's argument is lazy, so we make a thunk that
+promises to compute (/ 1 0) later, and that becomes the argument to FOO.
+If we use EVAL up there, as written, then FOO will get a thunk as its
+argument, and will return the thunk, which will become the value of P.  If
+we make it ACTUAL-VALUE, then the thunk will be forced, and we'll get an
+error dividing by zero, and P won't get a value.
+
+I think the procedure FOO probably doesn't care whether or not its argument is
+a thunk, and therefore the argument shouldn't be forced.  If the return value
+from FOO is used in some context where a real value is needed (for example,
+if we said
+	(foo (baz (/ 1 0)))
+at the Scheme prompt instead of inside a DEFINE, then the value will be
+forced.)  But you'd like to be able to write something like
+
+	(define (cadr seq) (car (cdr seq)))
+
+and if this is applied to a list of thunks, the result should be a
+thunk, not the value promised by the thunk.
+
+Perhaps there should be a third parameter type tag, so you could say
+
+	(define (f a (b lazy) c (d lazy-memo) (e forced))
+	  ...)
+
+allowing the user to choose between EVAL and ACTUAL-VALUE here.  This would
+add a COND clause in APPLY:
+
+	       ((eq? (cadar formals) 'forced)
+		(cons (actual-value (car args) env)
+		      (process-args (cdr args) (cdr formals) env)))
+
+
+Now we have to do a little data abstraction:
+
+(define (delay-nomemo exp env)
+  (list 'THUNK-NOMEMO exp env))
+
+(define (delay-memo exp env)
+  (list 'THUNK-MEMO exp env))
+
+Note that the thunk constructors don't have to do any real memoization or
+non-memoization work; they just construct thunks that "know" which kind they
+are.  It's when the thunks are forced that we have to take the difference
+into account:
+
+(define (force-it obj)
+  (cond ((THUNK-MEMO? obj)		; two kinds of thunk testers
+         (let ((result (actual-value
+                        (thunk-exp obj)
+                        (thunk-env obj))))
+           (set-car! obj 'evaluated-thunk)
+           (set-car! (cdr obj) result)  ; replace exp with its value
+           (set-cdr! (cdr obj) '())     ; for memoized thunk
+           result))
+	((THUNK-NOMEMO? OBJ)	; nomemo thunk is EVALed each time it's forced
+	 (ACTUAL-VALUE (THUNK-EXP OBJ) (THUNK-ENV OBJ)))
+        ((evaluated-thunk? obj)
+         (thunk-value obj))
+        (else obj)))
+
+(define (thunk-memo? exp)
+  (tagged-list? exp 'thunk-memo))
+
+(define (thunk-nomemo? exp)
+  (tagged-list exp 'thunk-nomemo))
+
+Note that for both kinds of thunks we call ACTUAL-VALUE to cash in the promise;
+the difference is that for a memoized thunk we remember the result, whereas for
+a non-memoized thunk we don't.
+
+
+
+Handle-infix:  See proj4b solutions.