Reduction Rules
Reduction Rules:
How do we find out what a procedure does?
How do we INTERPRET a procedure?
To determine the result of a procedure call
Look at body of procedure.
(define foo
(lambda (x y)
(+ (* x 3) y)))
> (foo (+ 4 1) 7)
We can get the result by evaluating
(+ (* (+ 4 1) 3) 7)
Simple strategy:
The result of a procedure call may be obtained by
substituting the call's operands for the
corresponding variables in the procedure's body.
Too simple. We will need some restrictions....
Another way to express this kind of reasoning
about procedures is to do a derivation
(foo (+ 4 1) 7)
((lambda (x y) (+ (* x 3) y))
(+ 4 1)
7)
(+ (* (+ 4 1) 3) 7)
22
(foo (+ 4 1) 7)
(foo 5 7)
(+ (* 5 3) 7)
(+ 15 7)
22
We got the final answer by replacing calls to
procedures with literal arguments by
a literal representing the value of the
call
(define c+
(lambda (n)
(lambda (m)
(+ n m))))
> ((c+ 5) 3) ??
((lambda (m) (+ 5 m)) 3)
(+ 5 3)
8
let expressions:
We know that
(let ([var1 exp1]
[var2 exp2]
...
[varn expn])
body)
is equivalent to
((lambda (var1 ... varn) body) exp1 .. expn)
We know how to evaluate lambda expressions.
Therefore
When we want to evaluate a let expression
Convert to equivalent lambda expression
evaluate the lambda expression as before
(define c+
(lambda (n)
(lambda (m)
(+ n m))))
(let ([x 3]
[add5 (c+ 5)])
(add5 x))
(let ([x 3]
[add5 (lambda (m) (+ 5 m))])
(add5 x))
((lambda (x add5)
(add5 x))
3
(lambda (m) (+ 5 m)))
((lambda (m) (+ 5 m)) 3)
(+ 5 3)
8
Literal representation of values
versus
Values themselves
'(1 2 3)
(list 1 2 3)
Consider:
(let ([second (lambda (x) (car (cdr x)))])
(second (list 1 2 3)))
((lambda (second) (second (list 1 2 3)))
(lambda (x) (car (cdr x))))
((lambda (x) (car (cdr x)))
(list 1 2 3))
((lambda (x) (car (cdr x)))
'(1 2 3))
What's the difference with
((lambda (x) (car (cdr x)))
(1 2 3))
(car (cdr '(1 2 3)))
(car '(2 3))
2
Consider doing this kind of substitutions to
reason about procedures in a language so that we
can INTERPRET the language.
We will use the lambda calculus extended with
NUMBERS
Any language can be re-written in the lambda
calculus
Thus if we can reason about procedures in the
lambda calculus we can extend the results to
procedures in any programming language
((lambda (var) exp) rand)
is equivalent to the expression obtained by
replacing references to var in exp by rand
exp[rand/var]
using our alpha-conversion notation from chapter
2.
Of course we have to worry about conflicts due to
different uses of the same variable name.
Free variables in rand could be captured by
bindings of var in the lambda expression
or by
other lambda expression in exp
For example:
(define y
(lambda (n)
(lambda (m)
(+ n m))))
((lambda (x)
(lambda (y) (x y)))
(y w))
can be transformed into
(lambda (y) ((y w) y))
The reference to y in (y w) should remain free but
has been captured by the inner lambda expression
Our current transformation rule leads to
an incorrect interpretation of procedure's results
Correct transformation would change the name of
the inner variable y to something else
consider w
(define y
(lambda (n)
(lambda (m)
(+ n m))))
((lambda (x)
(lambda (w) (x w)))
(y w))
(lambda (w) ((y w) w))
NO
the name should be a name that does not occur free
in the argument (y w)
consider zz, it does not occur free in (y w)
(define y
(lambda (n)
(lambda (m)
(+ n m))))
((lambda (x)
(lambda (zz) (x zz)))
(y w))
This is provably equivalent to the original
expression because we are doing an
alpha-conversion using the provably correct
alpha-conversion rule
Thus:
(lambda (zz) ((y w) zz))
is a currect substitution
Formally, we need a transformation rule (similar
to the alpha-conversion rule) for
procedure application that avoids variable capture
We define this substitution rule for each kind of
expression in the lambda calculus.
An inductive definition to transfrom any
expression in the lambda-calculus
Substitute M for x in E --> E[M/x]
1. if E is the variable x
x[M/x] = M
2.a. if E is any other variable y
y[M/x] = y
y is distinct from x
2.b. if E is a constant c
c[M/x] = c
3. if E is an application (F G) then
(F G)[M/x] = (F[M/x] F[M/x])
It only gets interesting when we deal with the
Almighty
lambda
4. if E is of the form (lambda (y) E')
4.a. if E is of the form (lambda (x) E')
E[M/x] -->
(lambda (x) E')[M/x] = (lambda (x) E')
because the inner lambda creates a hole in the
scope of the outer x
4.b. if E is of the form (lambda (y) E') and
x does not occur free in E'
(lambda (y) E')[M/x] = (lambda (y) E')
if x does not occur free in E'
again nothing needs be done
4.c. if E is of the form (lambda (y) E') and
y does not occur free in M
(lambda (y) E')[M/x] = (lambda (y) E'[M/x])
if y does not occur free in M
4.d.if E is of the form (lambda (y) E') and
x occurs free in E' AND
y occurs free in M
you will get accidental capture.
Soln: Rename y using alpha-conversion to some
other name that does not occur free in E' or M
4.d.if E is of the form (lambda (y) E') and
x occurs free in E' AND
y occurs free in M
(lambda (y) E')[M/x] =
(lambda (z) (E'[z/y])[M/x])
where
z does NOT occur free in M or E'
Substitution for interpreting procedure calls
is defined by rules 1 - 4
Notationaly we write
((lambda (x) E) M) = E[M/x]
where E[M/x] is defined by our substitution rules
1 - 4.
This is also called a BETA-CONVERSION and an
expression of the form
((lambda (x) E) M)
to which this rule can be applied is called a
Beta-Redux
When the Beta-conversion rule is used in
left to right direction to transform an Beta-redux
it is called a Beta-reduction.
you can also use Beta-conversion in the right to
left direction
E[M/x] = ((lambda (x) E) M)
This is what is done when using let to avoid
repeating an expression
Consider:
((f (a (b c))) (a (b c)))
==>
((lambda (x) ((f x) x))
(a (b c)))
==>
(let ((x (a (b c))))
((f x) x))
Exercise 4.2.1
((lambda (x) (x (y x)))
z)
((lambda (x) (x y))
(lambda (y) (x y)))
((lambda (a) (a y))
(lambda (z) (x z)))
((lambda (z) (x z)) y)
Sushil Louis
Last modified: Mon Nov 1 10:32:43 PST 1999