1 Iterative procedures and assignment

advertisement
TDDC74 Programming: Abstraction and Modelling
PRAM, Tutorial 4, version 1 (vt 2011)
1
Iterative procedures and assignment
Problem 1 ------------------------------------------------------------------------------------------------------------------Translate the following recursive function (a recursive linear model) to an iterative function using
assignments.
Define first a recursive version doing the recursive iterative model. In the next step translate that
model to the iterative function.
You are supposed in the iterative version to use the loop-construct. The function merges two sorted
lists to one sorted list.
(define (merge lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1)
((< (car lst1) (car lst2))
(cons (car lst1) (merge (cdr lst1) lst2)))
(else (cons (car lst2) (merge lst1 (cdr lst2))))))
You may need a function add-to-end defined as
(define (add-to-end e lst)
(append lst (list e)))
(add-to-end ’x ’(1 2 3)) = (1 2 3 x)
1
2
Drawing Environment Diagrams
The following rules for the environment model are adapted from SICP 3.2.1:
1. A procedure is created by evaluating a lambda expression relative to a given environment.
The resulting procedure object is a pair consisting of the text of the lambda expression and
a pointer to the environment in which the procedure was created.
2. A procedure object is applied to a set of arguments by constructing a frame, binding the
formal parameters of the procedure to the arguments of the call, and then evaluating the
body of the procedure in the context of the new environment constructed. The new frame
has as its enclosing environment the environment part of the procedure object being applied.
3. Remember that let and define may hide implicit lambda. To make sure you do not forget
evaluating a lambda expression, rewrite let and define as explicit lambda.
4. Defining a symbol using define creates a binding in the current environment frame and
assigns to the symbol the indicated value.
5. (set! variable value) in some environment locates the binding of the variable in the
environment and changes that binding to indicate the new value. That is, one finds the first
frame in the environment that contains a binding for the variable and modifies that frame.
If the variable is unbound in the environment, then set! signals an error.
3
Procedure calls, local state and procedure objects
Problem 2 ------------------------------------------------------------------------------------------------------------------We start to analyze in an environment diagram what happens when we call a number of procedures,
where all procedures are defined on the top level. In the next step we analyze the same procedures,
but hey are definied as local procedures. Discuss the scope of the variables (parameters).
Three procedures defined on the top level.
(define (f x)
(+ (g (+ x 1)) 10))
(define (g y)
(+ (h (+ y 2)) 20))
(define (h z)
(+ z 50))
(f 1)
The same procedures but defined locally.
(define (f x)
(define (g y)
(define (h z)
(+ z 50))
(+ (h (+ y 2)) 20))
(+ (g (+ x 1)) 10))
(f 1)
2
Problem 3 ------------------------------------------------------------------------------------------------------------------Next we take a recursive procedure, the fibonacci function.
(define (fib n)
(define (fib-iter i fib-1 fib-2)
(if (= i n)
fib-1
(fib-iter (+ i 1) (+ fib-1 fib-2) fib-1)))
(cond ((= n 0) 0)
((= n 1) 1)
(else (fib-iter 2 1 1))))
Draw an environment diagram for (fib 4).
Problem 4 ------------------------------------------------------------------------------------------------------------------We want to create simple procedures which switch between #f and #t.
(define (make-flip state)
(lambda ()
(begin (set! state (not state))
state)))
which is the same as
(define make-flip
(lambda (state)
(lambda ()
(begin (set! state (not state))
state))))
(define flip-1 (make-flip #f))
(flip-1)
(flip-1)
(define flip-2 (make-flip #t))
(flip-2)
(flip-2)
(flip-1)
Draw environment structures to analyze the code above.
Problem 5 ------------------------------------------------------------------------------------------------------------------Next example has a let-expression outside the lambda-expression, which is the returned procedure.
(define (make-adder start-value)
(let ((value start-value))
(lambda (dx)
(if (eq? dx ’start-again)
(set! value start-value)
(begin (set! value (+ value dx))
value)))))
(define add-1 (make-adder 10))
(add-1 5)
(add-1 7)
(add-1 ’start-again)
(define add-2 (make-adder 100))
(add-2 5)
Remember that let is simply syntactic sugar for a procedure call:
(let ((var exp)) body)
is interpreted as an alternate syntax for
((lambda (var) body) exp)
3
We suggest that you begin by rewriting make-adder to the second form.
Draw environment structures to analyze the code above.
Problem 6 ------------------------------------------------------------------------------------------------------------------There are times when we only need one procedure with a local state, and in those cases it is not
nececssary to write “procedure makers”, but simply to do it like this:
(define flip-3
(let ((state #f))
(lambda ()
(begin (set! state (not state))
state))))
(flip-3)
(flip-3)
Again, draw an environment diagram to analyze the code above.
4
Download