|
|
|
Purpose: |
|
|
|
In this phase we transform the calculator language into a mini Lisp-like language by adding structured data in the form of s-expressions. |
Background: |
|
|
|
|
|
S-expres- sions As Data |
Before I can specify the details of the project I must
first tell you about how s-expressions are used as data in
Lisp. So far we have only simple data types: numbers and
strings. In Lisp s-expressions are provided as the principal
way of building up compound data structures out of the base
types which include not only numbers and strings but also
symbols, which so far we have used just for
variable names. Lists are constructed using the
In general, a cons pair is written by writing
the two items of the pair inside parentheses, separated by a
" The empty list can be written either as |
|
CAR and CDR |
To get the first thing in a cons pair the function
We use these functions as follows: > (define a (cons 2 (cons 6 (cons -3 ()))))
a <- (2 6 -3)
> (car a)
2
> (cdr a)
(6 ~3)
> (car (cdr a))
6
The operations |
|
Quote |
Now, obviously, it would be nice if we could just type
> (define a (2 6 -3))
>>Error: Unknown operator 2 in (FUNCTION 2)
Since we are also using the s-expression syntax for our
program syntax, the interpreter sees a list of things in
parentheses as a request to treat the first item as a
function and send the rest of the items to it as arguments.
Of course, The way around this is the > (define a (quote (2 6 -3)))
a <- (2 6 -3)
> (+ 2 3)
5
>(quote (+ 2 3))
(+ 2 3)
>(car (+ 2 3))
Runtime Error -- Illegal argument to car.
>(car (quote (+ 2 3)))
+
For any expression Notice
> '(2 6 -3)
(2 6 -3)
> ' '(2 6 -3)
(quote (2 6 -3))
|
|
Symbols as Data |
Now, with quote, it becomes meaningful to have symbols as
data. Suppose
> (define a 3)
a <- 3
> (define b 4)
b <- 4
> a
3
> 'a
a
> (+ a b)
7
> (+ 'a b)
Runtime Error -- Illegal operands to math function +
> (car '(a b))
a
> (+ (car '(a b)) b)
Runtime Error -- Illegal operands to math function +
So, once they've been quoted, symbols are just symbols. They become pretty much like the elements of an enumerated type. Note, this is not true of numbers or > 3 3 > '3 3 > (+ 3 4) 7 > (+ '3 4) 7 >'(3 4) (3 4) > (car '(3 4)) 3 > (+ (car '(3 4)) 4) 7 Note that explicite use of > '3 3 > ''3 (quote 3) That's because your not quoting the three (vaculously) and then quoting it again. Rather, you are quoting the act of quoting the three. As a more complete example, if we wish to search a list for a value, we can use the following code:
(define (memb val list)
(cond ((null list) ())
((= val (car list)) 'T)
(memb val (cdr list))))
Here |
|
Boolean Values |
The standard treatment of boolean values in Lisp is
somewhat analagous to that used in C and C++. The empty list
( Remember that when |
|
Richer Data Structures |
Because s-expressions don't have to be homogeneous like ML lists, they can be used to build arbitrary data structures. For instance, we can represent a binary search tree as a three element list, the first element of which is the root, the second of which is the left sub-tree, and the third of which is the right sub-tree. As in:
'(4 (2 (1 () ()) (3 () ())) (8 (6 (5 () ()) (7 () ())) (9 () ())))
which can be seen as representing the binary search tree: ![]() To make this clearer, imagine it formatted as: '(4
(2
(1 () ())
(3 () ()))
(8
(6
(5 () ())
(7 () ()))
(9 () ())))
Using this representation, the function to determine if a tree contains a given value would be: (defun (tree_memb val tree)
(cond ((null tree) ())
((= val (car tree)) 'T)
((< val (car tree)) (tree_memb val (car (cdr tree))))
('T (tree_memb val (car (cdr (cdr tree)))))))
Of course, it would be better to impose some level of data abstaction by first defining some methods and using them, as in: (defun (empty tree) (null tree))
(defun (root tree) (car tree))
(defun (left-subtree tree) (car (cdr tree)))
(defun (right-subtree tree) (car (cdr (cdr tree))))
(defun (tree_memb val tree)
(cond ((empty tree) ())
((= val (root tree)) 'T)
((< val (root tree)) (tree_memb val (left-subtree tree)))
('T (tree_memb val (right-subtree tree)))))
|
What I Have Provided: |
|
|
|
In order to support the use of s-expressions as data, the
type The code for As stated above, the parser is already set up so that if
the user types I have created a version of the SML-NJ interpreter with
the parser structure You may find it useful to diff the new version of syntaxconverter.sml against the one from the last project to get a sense of the changes. (I have also loaded a sample solution to the evaluator functor and built a structure called testEvaluator as well. You can use the functions in this structure from the SML command line to see what the results of evaluation should be.) I have also provided an executable sample solution at
Finally, the file |
What You Need To Do: |
|
|
|
|
What to Submit: |
|
|
|
As with the last project, only the evaluator and the
syntax converter get appreciable changes in this phase. And,
as before, the changes to the syntax converter and user
interface have already been made for you. Therefore, you
should submit just the new implementation of
The make file in the |
|
|
This page copyright ©2000 by Joshua S. Hodas. It was built on a Macintosh. Last rebuilt on Fri, March 31, 2000. |
http://cs.hmc.edu/~hodas/courses/cs131/projects/project07.html |
|