Homework 5 (Due Friday 2/19/2009 at 10:00am)
Submit this assignment via Owl-Space In contrast to the previous assignments, submit each problem in a separate .ss file: 1.ss, 2.ss, 3.ss, and 4.ss (if you do the extra credit problem). Unfortunately, none of the languages supported by DrScheme will allow these files to be combined. The Pretty Big Scheme language allows top-level indentifiers (functions and variables) to be redefined, but it does not support check-expect. All of the student languages--the only ones that support check-expect--prohibit redefinition.
Embed answers that are not program text in a Scheme block comment or block commenting brackets (#| and |#).
Use the Intermediate Student with lambda language.
Given the Scheme structure definitions:
(define-struct sum (left right)) (define-struct prod (left right)) (define-struct diff (left right)) (define-struct quot (left right))
an arith-expr is either:
- a number
n, - a sum
(make-sum ae1 ae2), - a product
(make-prod ae1 ae2), - a difference
(make-diff ae1 ae2), or - a quotient
(make-quot ae1 ae2)
where n is a Scheme number, and ae1 and ae2 are arith-exprs.
The following 4 exercises involve the data type arith-expr. If you are asked to write a function(s), follow the design recipe: contract, purpose, examples/tests, template instantiation, code, testing (which happens automatically when the examples are given in (check-expect ...) form). Follow the same recipe for any help function that you introduce.
- (40 pts.) Write an evaluator for arithmetic expressions as follows:
- Write the (function) template for
arith-expr Write a function
to-listthat maps anarith-exprto the corresponding "list" representation in Scheme. Numbers are unchanged. Some other examples include:(to-list (make-sum (make-prod 4 7) 25)) => '(+ (* 4 7) 25) (to-list (make-quot (make-diff 4 7) 25)) => '(/ (- 4 7) 25)
Note: you need to define the output type (named
scheme-expr) for this function, but you can omit the template because this assignment does not include any functions that process this type.- Write a function
eval: arith-expr -> numberthat evaluates anarith-expr. Your evaluator should produce exactly the same result for anarith-expr Ethat Scheme evaluation would produce for the list representation(to-list E).
- Write the (function) template for
- (40 pts.) Extend the definition of
<arith-expr>} as follows:- Add a clause for variables represented as Scheme symbols.
- Write the (function) template for this definition.
- Modify your definition of
to-listto support the new definition of arith-expr. Given the Scheme structure defintion:
(define-structure binding (var val))
a
bindingis(make-binding s n)wheresis a symbol andnis a number and anenvironmentis a(list-of binding). Write a (function) template for processing anenvironment.- Define a top-level variable (constant)
empty-envthat is bound to the empty environment. Write a function
extendthat takes environmentenv, a symbols, and a numbern,
and returns an extended environment identical toenvexcept that it adds the additional binding ofston.
The definition ofextendtrivial; it requires no recursion. As a result,extendsatisfies the invariant(check-expect (extend empty-env s n) (list (make-binding s n)))
In the remainder of the problem, use
empty-envandextendto define example environments for test cases.- Write a function
lookupthat takes a symbolsand an environmentenvand returns the first binding inenvwith avarcomponent that equalss. If no match is found,lookupreturns empty. Note that the return type oflookupis not simplybinding. Define the a new union type calledoption-bindingfor the the return type. Write a new
evalfunction for the new definition ofarith-expr. The newevaltakes two arguments: anarith-expr Eto evaluate and anenvironment envspecifying the values of free variables inE. For example,(eval 'x (extend empty-env 'x 17)) => 17 (eval (make-prod 4 7) (extend empty-env 'x 17)) = 28 (eval 'y (extend empty-env 'x 17)) => some form of run-time error
If an
arith-expr Econtains a free variable that is not bound in theenvironment env, then(eval E env)will naturally produce some form of run-time error if you have correctly codedeval. Do not explicitly test for this form of error.
- (20 pts.) An
environmentis really a finite function (a finite set of ordered pairs). It is finite in the sense that it can be completely defined by a finite table, which is not true of nearly all the primitive and library functions in Scheme (and other programming languages). Even the identity function is not finite. For the purpose of this exercise, we redefine the typeenvironmentas(symbol -> option-binding).- Rewrite
evalto useenvironmentdefined as a finite function in(symbol -> option-binding)instead of as a(list-of option-binding). If you cleanly coded your definition ofevalin the preceding problem usinglookup,make-binding, andextend, all that you have to do to your solution to the previous problem is
redefine the bindings oflookup,empty-env, andextend, and revise your test cases forextend. You can literally copy the entire text of your solution to problem 2; change the definitions oflookup,empty-env, andextend; update your documentation (annotations) concerning theenvironmenttype; and revise your tests forextend. Note thatextendcannot be tested (since the result is a function!) without usinglookupto examine it. (If you wrote a correct solution to problem 2, you can do this problem is less than 15 minutes!)
Hint: you can uselambda-notation to define a constant function forempty-envandextendcan be defined as a functional that takes a function (representing an environment) and adds a new pair to the function--using aifembedded inside alambda-expression.
- Rewrite
- Extra Credit (50 pts.) Add support for
lambda-expressions in your evaluator as follows:- Extend the definition of
<arith-expr>by adding a clause for unarylambda-expressions and a clause for unary applications of anarith-exprto anarith-expr. Use the namelamfor the structure representing alambda-expression and the namesvarandbodyfor the accessors of this structure. Use the nameappfor the structure representing an application and the namesheadandargfor the accessors of this structure. Note that the head of anappis anarith-exprnot alam. - Write a (function) template for the newest definition of
arith-expr. - Extend the definition of
to-listto support the newest definition ofarith-expr. - Extend the definition of
evalto support the newest definition ofarith-expr. Note thatevalcan now return functions as well as numbers. Your biggest challenge is determining a good representation for function values. What doesevalreturn for alaminput? That input may contain free variables. In principle, you could represent the value of thelaminput by a revisedlam(with no free variables) obtained by substituting the values for free variables from the environment input (just like we do in hand-evaluation). But this approach is tedious and computationally expensive. A better strategy is to define a structure type (called a closure) to represent a function value. The structure type must contain the originallamand a description of what substitution would have been made, deferring the actual substitution just asevaldefers substitutions by maintaining an environment.
- Extend the definition of