[plt-scheme] HTDP 12.4.2

From: Stephen Bloch (sbloch at adelphi.edu)
Date: Fri Jun 23 09:47:22 EDT 2006

At 12:20 PM -0700 6/22/06, Danny Yoo wrote:
>Imagine for the moment that insertEverywhere is working, and imagine 
>us calling it on the test example.  Since the list isn't empty, 
>we'll be hitting the else body, and we're running into:
>
>      ... sym ... (first alow) ...
>      ... (insertEverywhere sym (rest alow)) ...
>
>We know that we want to get out:
>
>     (list (list 'd 'e 'r)
>           (list 'e 'd 'r)
>           (list 'e 'r 'd)
>           (list 'd 'r 'e)
>           (list 'r 'd 'e)
>           (list 'r 'e 'd))
>
>Again, putting on our "wishing" hat, let's look at the recursive 
>call to insertEverywhere.  What does it give us?
>
>     (insertEverywhere sym (rest alow))
>
>     ==>
>
>     (insertEverywhere 'd (rest (list (list 'e 'r)
>                                      (list 'r 'e))))
>
>     ==>
>
>     (insertEverywhere 'd (list (list 'r 'e)))
>
>     ==> (list (list 'd 'r 'e)
>               (list 'r 'd 'e)
>               (list 'r 'e 'd))
>
>(This would be a good test case to add to your test suite.)
>
>
>
>So, if we are holding onto:
>
>    (list (list 'd 'r 'e)
>          (list 'r 'd 'e)
>          (list 'r 'e 'd))
>
>and we want to mess with it enough so we get:
>
>     (list (list 'd 'e 'r)
>           (list 'e 'd 'r)
>           (list 'e 'r 'd)
>           (list 'd 'r 'e)
>           (list 'r 'd 'e)
>           (list 'r 'e 'd))
>
>do you see what the difference between what we're holding onto and 
>what we want is?  Can you give a concept or name to it?

Here's how I teach this approach in class.

We've already gotten used to writing function templates that list all 
the "interesting expressions" we're likely to need:

(define (insertEverywhere sym alow)
    sym
    alow
    (cond [(empty? alow) ...]
             [(cons? alow)
                (first alow)
                (rest alow)
                (insertEverywhere (rest alow))
              ]))

If this is enough to tell you how to write the program, great.  If 
not, we go to Plan B, the "template with types", in which we annotate 
each of the expressions in the template with its TYPE.  It may also 
be helpful at this point to add a line for "desired answer":

(define (insertEverywhere sym alow)
    sym                                                 a symbol
    alow                                                a list of 
words, i.e. a list of lists of symbols
    (cond [(empty? alow) ...]
             [(cons? alow)
                (first alow)                          a word, i.e. a 
list of symbols
                (rest alow)                          a list of words, 
i.e. a list of lists of symbols
                (insertEverywhere sym (rest alow)) a list of words, 
i.e. a list of lists of symbols
     desired answer                               a list of words, 
i.e. a list of lists of symbols
              ]))

If this gives you a brilliant idea, great.  If not, we go to Plan C, 
the "template with values".  Pick a MODERATELY COMPLICATED example 
(you've already written the examples, and at least one of them should 
be moderately complicated), and write down, next to each expression 
in the template, its value for that example.  So suppose we picked
(insertEverywhere 'd (list (list 'x) (list) (list 'y 'z)))
"should be" (list (list 'd 'x) (list 'x 'd) (list 'd) (list 'd 'y 'z) 
(list 'y 'd 'z) (list 'y 'z 'd))
The template would become

(define (insertEverywhere sym alow)
    sym                                   a symbol:                  'd
    alow                                  a list of words: 
(list (list 'x) (list) (list 'y 'z))
    (cond [(empty? alow) ...]
             [(cons? alow)
                (first alow)           a word:                      (list 'x)
                (rest alow)            a list of words:          (list 
(list) (list 'y 'z))
                (insertEverywhere sym (rest alow)) a list of words: 
(list (list 'd) (list 'd 'y 'z) (list 'y 'd 'z) (list 'y 'z 'd))
     desired answer                 a list of words:    (list (list 'd 
'x) (list 'x 'd) (list 'd) (list 'd 'y 'z) (list 'y 'd 'z) (list 'y 
'z 'd))
              ]))

Now, compare the "desired answer" with the various expressions you've 
got available on the preceding lines.  95% of the time, the recursive 
call will give you most of the right answer, and you just have to 
identify what needs to be added to it to get the complete right 
answer.

This approach will serve you well not only for this function but for 
"intersperse", and any other auxiliary functions you may need.

Note the importance of picking a NON-TRIVIAL example: if you pick an 
example that's too simple, the pattern-recognition circuits in your 
brain don't have an opportunity to kick in and spot what parts of the 
"desired answer" match what available expressions.  Likewise, the 
fact that the example wasn't a "special case" (in which all the input 
words were anagrams of one another) makes it easier for the 
pattern-recognition circuits to do their job.
For example, if you picked

(insertEverywhere 'd (list (list 'x)))
"should be" (list (list 'd 'x) (list 'x 'd))

as your example, the template with values would be only

(define (insertEverywhere sym alow)
    sym                                   a symbol:                  'd
    alow                                  a list of words: 
(list (list 'x))
    (cond [(empty? alow) ...]
             [(cons? alow)
                (first alow)           a word:                      (list 'x)
                (rest alow)            a list of words:          empty
                (insertEverywhere sym (rest alow)) a list of words:  empty
     desired answer                 a list of words:    (list (list 'd 
'x) (list 'x 'd))
              ]))

which isn't nearly as informative.


In my classroom experience, this "template with values" strategy can 
be helpful in many settings, but it's MOST helpful in writing 
functions that return lists or other self-referential data structures.

-- 
					Stephen Bloch
					sbloch at adelphi.edu


Posted on the users mailing list.