Imperative Programming
Test:
Q1. Most got it right.
(lambda (x)
(lambda (y)
((lambda (x)
(x y))
x)))
(lambda (z)
((lambda (a b c)
(a (lambda (a) (+ a c)) b))
(lambda (f x)
(f (z x)))))
Q2. Few mistakes:
(lambda (x y)
((lambda (a)
(x (a y)))
x))
(lambda (x y)
(lambda (a)
((x : 1 0) ((a : 0 0) (y : 1 1))))
(x : 0 0))
(lambda (x) x)
(lambda (x) (x : 0 0))
Q2.
(lambda 1
(lambda 1
(: 1 0)))
(lambda (x)
(lambda (y)
x))
extend-ff*
Solved on page 94 in the textbook:
(define extend-ff*
(lambda (sym-list val-list ff)
(if (null? sym-lst)
ff
(extend-ff (car sym-list) (car val-list)
(extend-ff*
(cdr sym-list)
(cdr val-list)
ff)))))
Beta-Conversion
((lambda (x)
(lambda (y) (x y)))
(y w))
==>
(lambda (z) ((y w) z))
((lambda (x) (x y))
(lambda (y) (x y)))
==>
((lambda (y) (x y)) y)
(lambda (x)
((lambda (x) (y x)) z))
Not a Beta-redex
Only applications are beta-redexes
(define parse
(lambda (datum)
(cond
[(number? datum) (make-lit datum)]
[(symbol? datum) (make-varref datum)]
[(if-exp? datum) (make-if
_(parse (cadr datum))_
_(parse (caddr datum))_
_(parse (cadddr datum))_)]
[(pair? datum)
(if (eq? (car datum) 'lambda)
(make-lambda (caadr datum) (parse (caddr
datum)))
(make-app (parse (car datum))
(parse (cadr datum))))]
[else (error 'parse
"Invalid concrete syntax")])))
(define unparse
(lambda (exp)
(variant-case exp
[lit (datum) datum]
[varref (var) var]
[if (test-exp then-exp else-exp)
(list 'if
_(unparse test-exp)_
_(unparse then-exp)_
_(unparse else-exp)_)]
[lambda (formal body)
(list
'lambda (list formal) (unparse body))]
[app (rator rand)
(list (unparse rator) (unparse rand))]
[else (error 'unparse
"Invalid abstract syntax expression")])))
Leftmost reduction:
Since applicative-order reduction can be caught in
an infinite loop
((lambda (y) 3
(lambda (x) (x x)) (lambda (x) (x x))))
Is there a reduction strategy which is guaranteed
to find the answer if it exists?
Answer: Yes ==> Leftmost reduction:
reduce the Beta-redex whose left paren
comes first.
Advantages:
Guaranteed to find normal form.
Normal form: Expression has no Beta-redexes
Disadvantage:
Efficiency:
((lambda (x) (x (x y)))
((lambda (w) w) z))
==>
(((lambda (w) w) z)
(((lambda (w) w) z)
y))
==>
(z (((lambda (w) w) z) y))
==>
(z (z y))
IF we reduce the operand first, we need fewer
reductions:
((lambda (x) (x (x y)))
((lambda (w) w) z))
==>
((lambda (x) (x (x y))) z)
(z (z y))
Imperative programming:
Scheme so far has been purely
FUNCTIONAL:
AN EXPRESSION ONLY EVALUATED FOR ITS VALUE
Advantages:
No other effects of evaluation need be
considered
Many problems can be solved easily
Easy to reason about functional programs using
simple, but powerful, rules.
Disadvantages:
Some cases, functional programming is awkward or
inefficient.
Therefore:
IMPERATIVE PROGRAMMING:
operations are performed not to obtain a value but
rather for some SIDE EFFECT on the computation
Broadly:
ASSIGNMENT and I/O ops
Disadvantages:
Difficult to reason about
Beta/eta reductions not applicable
example:
Leftmost reduction:
Multiple copies of an operand made as part of a
reduction. If further reduction of these copies
involves side-effects, these will happen multiple
times
Start with sequencing and other imperative ops
needed for later.
Statement: evaluated/performed purely for side
effect
Sequencing refers to the order in which
side-effects are performed.
(begin e1 e2 ... en)
e1, e2, ..en evaluated in order.
value of begin expression is value of en
> (begin (display "Two plus two = ")
(display (+ 2 2)))
Two plus two = 44>
???
Values returned by display are not specified.
True for most side-effect procedures
extra 4 result of (display (+ 2 2)) the result
returned by en in (begin e1 ... en)
> (begin (display "Two plus two = ")
(display (+ 2 2))
(newline))
Two plus two = 4
()
>
() returned by newline....?
What does our version of scheme do?
Let us define a for-each that is somewhat like map
this applies a procedure in a left to right order
on the members of a list.
(define for-each
(lambda (proc lst)
(if (null? lst)
'done
(begin
(proc (car lst))
(for-each proc (cdr lst))))))
> (displayln 2 "+" 2 "=" (+ 2 2))
2+2=4
>
Implied sequencing in bodies of lambda, let,
letrec, and in consequents of
cond, case, and variant-case.....
(define displayln
(lambda lst
(for-each display lst)
(newline)))
(define fact
(lambda (n)
(displayln "Entering fact with n = " n)
(let ([ans (if (zero? n)
1
(* n (fact (sub1 n))))])
(displayln "Returning from fact with " ans)
ans)))
> (fact 3)
Entering fact with n = 3
Entering fact with n = 2
Entering fact with n = 1
Entering fact with n = 0
Returning from fact with 1
Returning from fact with 1
Returning from fact with 2
Returning from fact with 6
6
>
Sushil Louis
Last modified: Mon Oct 18 17:44:40 PDT 1999