lyman@cc.gatech.edu
Step 1. loaded (or evaluated) the init.lisp file that you downloaded in Lab 1.
Step 2. You should download the file ~gt7510f/2360/lab4.lisp at this time, also. Do not evaluate this file. Simply open it into a Fred Buffer.
P.S. For the actual lab sessions there were two files. lab4.1.lisp and lab4.2.lisp. This a, hopefully, a clearified version (v02 ) of the handout and there is one file lab4.lisp which is a superset of the material that is in the split versions. [ There is an additional very tricky evaluation example and a more "powerful" use of trace used. ]
The first section in the lisp file for this lab contains some expression that you will evaluate using the stepper. What you are to do is before evaluating the expression you should type into your file the value you expect to be returned in the appropriate spot. Then evaluate the expression. For example
(step (cons '7 '(cdr '(a b))) )
;;; Expectation:
;;; Actual:Note, you can ignore the
step wrapped around the inner expression. Step will only
return the value of the expression that is passed in. Remember also that step is a special
form so its arguments are not evaluated. It is simply called for the "side effect" of allow
you to step through the evaluation process.
Let say that I expected this expression to evaluate to ( 7 B ). I would enter this
expression under the expression to be stepped before executing the step. Next I would
position the cursor just to the right of the right most parenthesis and type Ctrl-C Ctrl-E to
evaluate this expression. After stepping through the expression I would enter the actual
result underneath my expectation. If the two do not match try to figure out why. If you are
mystified as to what happened then ask your TA (or your neighbor or hack around with
the Listener a bit).
Warning: not all of the expression are legal expressions. Some may drop you into the debugger.
By the way the above evaluates to:
( 7 CDR ( Quote ( A B )))
Numbers are self evaluating, but quoting them doesn't hurt (it is unnecessary though,
you'd never should do that in real code.). The trick to this expression is that the cdr
expression is quoted. Which means it will not be evaluated. So it becomes a list. Effectively
the two following expression produce the exact same thing.
(list 'cdr (list 'quote (list 'a 'b)))
'(cdr (quote (A b ))
At this point do the evaluation exercises in the lab4.lisp file now. Stop when you get to the section on Stepping Through a Search. The prelude to that is described in the next section.
So algorithms influence the design of ADTs and ADTs influence the design of algorithms. A sort of ying-yang sort of thing.
At this point, highlight from the start of the Tree ADT down to and including the search function. [Hold the mouse down and move to the bottom of the buffer. It will scroll automagically for you. Stop once have included everything including search. The place to stop is marked in the file.] From the Eval menu, select Evaluate Selection. [There is a way to do something similar in GNU Emacs.]
You could sit there and read all the operators that are defined for the tree ADT. They all
have the prefix tree- . Or you go to the Tools Menu and select"List Definitions" and get
an overview of the operations that are currently specified.
The Tree you are going to play with looks like this
Alexander
/ \
Moog Worf
/
KurnCurrently a tree has the following implementation.
A tree is either the empty tree ---> ()
or an interior node ---> ( id left-sub-tree
right-sub-tree )
where left-sub-tree and right-sub-tree are also trees. ( a recursive definition)
A tree of height one might look like
(worf () () )
The tree you are going to play with looks like:
(alexander (moog () () ) ( worf ( kurn () () ) () )
( step ( tree-search 'Worf *tree1* ) )While you are steeping through this search try to anticipate what the
tree-* operators
will do before you enter that call. You may step over operators if you wish. If you step over
the recursive call then all you will see is the answer.
Or you can think of key arguments as optional arguments with names. Sometimes you would like to express a new value for the third "optional" argument without expressing values forthe first two. This is when key arguments come in handy.
The name of a key argument is given by a keyword. A keyword is a symbol prefixed with a colon. For example.
:test
:initial-element
:foobarare all keywords.
For example, type in the following two expressions into the Listener. (By default member
uses eql to test for equality. )
(member '(a) '( (a) b c ))
(member '(a) '( (a) b c ) :test #'equal )In the latter the argument with the name
:test is given the value of #'equal. Its default
value is #'eql. [ Try evaluating #'equal in the Listener if you are not sure what its
value is. ]
You may see keyed arguments in some of your TA's and/or Instructor's code. Your functions need not provide them. They may be useful to use from time to time though.
Here are some more examples of using key arguments ( the first two aren't but they'll help you see why the second two look the way they do )..
(sort '( 1 5 4 2 ) #'> )
(sort '("a" "b" "c" "d") #'string> )
(sort '((1 "a" ) (5 "b" ) (4 "c") (2 "d" )) #'> :key #'first )
(sort '((1 "a" ) (5 "b" ) (4 "c") (2 "d" )) #'string> :key #'second )
So what does
(trace (tree-search :before :print :step step-on-worf ) )do? What this will do is "trace" the function tree-search. However, it will only print upon entering the function ( and not at all on exit ). And it will start the stepper when the
step-on-worf function returns T. [ See the "Its Tool Time" page under the alternative
resources homepage for more information on using the stepper and trace facilities for both
MCL and LCL. ]
You should try tracing at this point. Once you land in the stepper press the EVAL button
on the stepper window. Enter tree as the expression to evaluate.
As you should be able to see we've "skipped over" stepping through the other parts of the original tree. This is very useful when you know here you want to stop and step, but need to traverse a tangle of function calls to get there.
The downside is that you have to be able to write the correct Lisp expression that will stop you in the right place.
The example following this one in the lisp file uses break-step-on-worf which will
drop you into the debugger. If you continue you'll drop into the stepper. This is useful if
you want to check out the backtrace before you start stepping.
At this point you should have a pretty good understanding of what the opertors of the tree ADT do and what the implementation of the ADT looks like. You will modify and extend this ADT in the next section.
Your job is modify the tree ADT so that it can handle n-ary trees and so that each tree node contains some more information than is there now.
Currently a non-empty tree node contains the following information:
Your job is to modify this ADT to handle trees with the following information:
HINT: Do you really need to change the operator's interface or just their internals?
HINT: Do you need to change the tree-search code at all?
WARNING: As you change the ADT operators make sure to evaluate them. If you change them incrementally remember which ones have been changed and which ones haven't. If you have a new operator calling an old operator you likely to get inconsistant results.
NOTE: Interpret tree-left-child and tree-right-child to return the leftmost
and rightmost children respectively. For a binary tree this is obvious. For an k-ary tree this
is different.
NOTE: if you want to keep the old versions of these functions do a "Save As..." to save the file under a different name before you start to make modifications.
tree-messy-search. Here the writer violated
the provided abstraction barrier willy-nilly. You job is to get tree-messy-search to work
now that you have changed the underlying implementation. [ Once again, don't use the
tree ADT operators. Write the appropriate Lisp code. ]
There is a tradeoff in layering your ADT operators. If you define you more sophisticated operators in terms of the more simpler ones then making a change to the implementation doesn't propogate into as many ADT operators as when you do not. However, you pay some "speed" cost in traversing the extra level of functions.
In this example tree-search is not an essential ( or fundalmental ) tree operator. So it kind of makes sense to use the more fundalmental operators to implement it.
You may also take the emacs competency test during lab also.