Title: Functions and Recursion
1 210
High Level Languages
Java (Object Oriented) ASP RDF (Horn
Clause Deduction, Semantic Web)
This Course
Jython in Java
Relation
3let transformation, differed substitution and
closures, and interpretation in FAE let
transformation (let ((A B)) C) ((lambda (A)
C) B) A B ---------------- C
------------------- A
---------- B -------- C (let (( x 3)) (let ((f
(lambda (y) ( x y)))) (f 4)) ((lambda (x)
((lambda (f) (f 4)) (lambda (y) ( x y))))
3) (app (fun 'x app (fun 'f app (id 'f) (num
4)) (fun 'y (add (id 'x) (id 'y)))) (num 3))
(app ------- arg1
------------------ ------------arg2--------------
- (app ---------------------------------------
arg1-------------------------------------
--arg2 Differed substitution and closures (aSub
'f (closureV 'y (add (id 'x) (id 'y)) (aSub 'x
(numV 3) (mtSub))) (aSub 'x (numV 3)
(mtSub))) Interpretation (interp (app (id 'f)
(num 4)) (aSub 'f (closureV 'y (add (id 'x) (id
'y)) (aSub 'x (numV 3) (mtSub))) (aSub 'x (numV
3) (mtSub))))
(numV 7)
4 Eduardo Saenz (anon. to classmates) (1 day
ago) - If our AST does not have let class nodes,
then when our interpreter visits every node of
the AST, making the environment of differed
substitutions along the way, our environment will
only have closures? You only do (aSub x 3
(mtSub)) when you encounter a let, and since our
parser converts lets to lambdas we'll never see
this type of differed substitution in our
environment only closures in our environment. Is
this logic correct? Philip Cannata (Instructor) (
Just now) - This is a good observation but try to
understand the following three cases that can
occur and see if you can distinguish when
deferred substitution should be done in each of
them and when function application should be
done gt (parse '(with (f (fun (x) x)) 5)) (app
(fun 'f (num 5)) (fun 'x (id 'x))) gt (interp
(parse '(with (f (fun (x) x)) 5)) (mtSub)) (numV
5) gt (parse '(with (f (fun (x) x)) (f 5))) (app
(fun 'f (app (id 'f) (num 5))) (fun 'x (id
'x))) gt (interp (parse '(with (f (fun (x) x)) (f
5))) (mtSub)) (numV 5) gt (parse '(with (f (fun
(x) x)) ((fun (y) ( y 2)) 5))) (app (fun 'f (app
(fun 'y (add (id 'y) (num 2))) (num 5))) (fun 'x
(id 'x))) gt (interp (parse '(with (f (fun (x) x))
((fun (y) ( y 2)) 5))) (mtSub)) (numV 7)
5Static and Dynamic Scoping Static
scoping (interp (parse 'with x 5 f 4)
(aSub 'f (closureV 'y (add (id 'x) (id 'y)) (aSub
'x (numV 3) (mtSub))) (aSub 'x (numV 3)
(mtSub)))) (numV 7) Dynamic Scoping (interp
(parse 'with x 5 f 4) (aSub 'f (closureV 'y
(add (id 'x) (id 'y)) (aSub 'x (numV 3) (mtSub)))
(aSub 'x (numV 3) (mtSub)))) (numV 9) Think
about this expression for both Static and Dynamic
Scoping (let ((z 3)) (let ((d 3) (f (lambda (x)
x))) (let ((z 27))
(let ((z 3) (a 5) (x (lambda (x y) ( x ( y
z))))) (let ((z 9) (a 7)) (x z a))))))
6PLAI Chapters 4, 5 and 6
Chapter 6, Pages 41 42 first-order Functions
are not values in the language. They can only be
defined in a designated portion of the program,
where they must be given names for use in the
remainder of the program. The functions in F1WAE
are of this nature, which explains the 1 in the
name of the language. higher-order Functions can
return other functions as values. first-class
Functions are values with all the rights of other
values. In particular, they can be supplied as
the value of arguments to functions, returned by
functions as answers, and stored in data
structures.
Page 27 - "
7 java crono.Crono (let ((z 17)) (let ((z 3) (a
5) (x (\ (x y) (- x ( y z))))) (let ((z 10) (a
5)) (x z a)))) Evaluating (let ((z 17)) (let
((z 3) (a 5) (x (\ (x y) (- x ( y z))))) (let
((z 10) (a 5)) (x z a)))) Environment empty
Evaluating (let ((z 3) (a 5) (x (\ (x y) (- x
( y z))))) (let ((z 10) (a 5)) (x z a)))
Environment z 17 Evaluating (\ (x
y) (- x ( y z))) Environment z
17 Result (\ (x y) (- x ( y z))) z 17
Evaluating (let ((z 10) (a 5)) (x z a))
Environment a 5 z 3
x (\ (x y) (- x ( y z))) z 17
Evaluating (x z a) Environment
a 5 z 10 x (\
(x y) (- x ( y z))) z 17 Evaluating
(- x ( y z)) Environment
y 5 z 17
x 10 Evaluating ( y z)
Environment y 5
z 17 x 10 Result 22
Result -12 Result -12
Result -12 Result -12 Result -12
In Crono, \ mean lambda
8In CronoOptions.java set public static boolean
ENVIRONMENT_DYNAMIC true Run ant to rebuild
crono. java crono.Crono (let ((z 17)) (let
((z 3) (a 5) (x (\ (x y) (- x ( y z))))) (let
((z 10) (a 5)) (x z a)))) Evaluating (let ((z
17)) (let ((z 3) (a 5) (x (\ (x y) (- x ( y
z))))) (let ((z 10) (a 5)) (x z a))))
Environment empty Evaluating (let ((z 3) (a
5) (x (\ (x y) (- x ( y z))))) (let ((z 10) (a
5)) (x z a))) Environment z 17
Evaluating (\ (x y) (- x ( y z)))
Environment z 17 Result (\ (x y)
(- x ( y z))) z 17 Evaluating (let ((z
10) (a 5)) (x z a)) Environment
a 5 z 3 x (\ (x y) (- x ( y
z))) z 17 Evaluating (x z a)
Environment a 5 z 10
x (\ (x y) (- x ( y z))) z 17
Evaluating (- x ( y z))
Environment a 5 y 5
z 10 x 10
Evaluating ( y z) Environment
a 5 y 5
z 10 x 10
Result 15 Result -5
Result -5 Result -5 Result -5 Result
-5
9(let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x
( y z))))) (let ((z 10) (a 5)) (x z (x 0 0)))))
Evaluating (let ((z 17)) (let ((z 3) (a 5) (x
(\ (x y) (- x ( y z))))) (let ((z 10) (a 5)) (x
z (x 0 0))))) Environment empty
Evaluating (let ((z 3) (a 5) (x (\ (x y) (- x (
y z))))) (let ((z 10) (a 5)) (x z (x 0 0))))
Environment z 17 Evaluating (\ (x
y) (- x ( y z))) Environment z
17 Result (\ (x y) (- x ( y z))) z 17
Evaluating (let ((z 10) (a 5)) (x z (x 0
0))) Environment a 5
z 3 x (\ (x y) (- x ( y z))) z 17
Evaluating (x z (x 0 0))
Environment a 5 z 10
x (\ (x y) (- x ( y z))) z 17
Evaluating (x 0 0)
Environment a 5 z 10
x (\ (x y) (- x ( y z))) z 17
Evaluating (- x ( y z))
Environment y 0
z 17 x 0
Evaluating ( y z) Environment
y 0 z 17
x 0 Result 17
Result -17 Result -17
Evaluating (- x ( y z))
Environment y -17 z
17 x 10 Evaluating ( y
z) Environment y
-17 z 17 x 10
Result 0 Result 10
Result 10 Result 10 Result 10 Result
10
Notice function application here.
10(let ((z 17)(i 22)) (let ((z 3) (a 5) (x (\ (x y)
(- x ( y z))))) (let ((z 10) (a 5)) (x z (x 0
((\ (x) x) i)))))) Evaluating (let ((z 17) (i
22)) (let ((z 3) (a 5) (x (\ (x y) (- x ( y
z))))) (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x)
i)))))) Environment empty Evaluating (let
((z 3) (a 5) (x (\ (x y) (- x ( y z))))) (let
((z 10) (a 5)) (x z (x 0 ((\ (x) x) i)))))
Environment i 22 z 17
Evaluating (\ (x y) (- x ( y z)))
Environment i 22 z 17
Result (\ (x y) (- x ( y z))) i 22, z 17
Evaluating (let ((z 10) (a 5)) (x z (x 0
((\ (x) x) i)))) Environment i
22 a 5 z 3 x (\ (x
y) (- x ( y z))) i 22, z 17
Evaluating (x z (x 0 ((\ (x) x) i)))
Environment i 22 a 5
z 10 x (\ (x y) (- x ( y
z))) i 22, z 17 Evaluating (x 0 ((\
(x) x) i)) Environment
i 22 a 5 z 10
x (\ (x y) (- x ( y z))) i 22,
z 17 Evaluating ((\ (x) x) i)
Environment i 22
a 5 z 10
x (\ (x y) (- x ( y z))) i 22,
z 17 Evaluating (\ (x) x)
Environment i
22 a 5 z 10
x (\ (x y) (- x ( y z))) i
22, z 17 Result (\ (x) x) i 22,
a 5, z 10, x (\ (x y) (- x ( y z)))
Result 22 Evaluating (- x ( y z))
Environment i 22
y 22 z 17
x 0 Evaluating ( y
z) Environment
i 22 y 22 z
17 x 0 Result 39
Result -39 Result -39
Evaluating (- x ( y z))
Environment i 22 y
-39 z 17 x 10
Evaluating ( y z)
Environment i 22
y -39 z 17 x 10
Result -22 Result 32
Result 32 Result 32 Result 32 Result
32
1110
High Level Languages
Java (Object Oriented) ASP RDF (Horn
Clause Deduction, Semantic Web)
This Course
Jython in Java
Relation
12Parameter and Arguments
Definitions An argument is an expression that
appears in a function application/call. A
parameter is an identifier that appears in a
function definition/declaration. In the code on
the right the call A(a, b) has arguments a and
b. The function declaration A has parameters x
and y.
int h, i void B(int w) int j 1, k
2 i 2w w w1
printf("In B - w, j, k, h, i d, d, d, d,
d\n", w, j, k, h, i) void A(int x, int y)
float i 1.1, j 2.2 B(h)
printf("In A - x, y, i, j, h d, d, f, f,
d\n", x, y, i, j, h) int main() int
a, b h 5 a 3 b 2 A(a,
b) printf("In Main a, b, h, i d, d,
d, d\n", a, b, h, i)
13Parameter Passing Mechanisms
- By value - Compute the value of the argument at
the time of the call and assign that value to the
parameter. So passing by value doesnt normally
allow the called function to modify an arguments
value. - By reference - Compute the address of the
argument at the time of the call and assign it to
the parameter. Passing by value allows the called
function to modify an arguments value. - By value-result
- By name
14int h, i void B(int w) int j 1, k
2 i 2w w w1
printf("In B - w, j, k, h, i d, d, d, d,
d\n", w, j, k, h, i) void A(int x, int y)
float i 1.1, j 2.2 B(h)
printf("In A - x, y, i, j, h d, d, f, f,
d\n", x, y, i, j, h) int main() int
a, b h 5 a 3 b 2 A(a,
b) printf("In Main a, b, h, i d, d,
d, d\n", a, b, h, i) ./a In B - w, j, k,
h, i 6, 1, 2, 5, 10 In A - x, y, i, j, h 3, 2,
1.100000, 2.200000, 5 In Main a, b, h, i 3, 2,
5, 10
int h, i void B(int w) int j 1, k
2 i 2(w) w w 1
printf("In B - w, j, k, h, i d, d, d, d,
d\n", w, j, k, h, i) void A(int x, int
y) float i 1.1, j 2.2
B(h) printf("In A - x, y, i, j, h d,
d, f, f, d\n", x, y, i, j, h) int main()
int a, b h 5 a 3 b 2
A(a, b ) printf("In Main a, b, h,
i d, d, d, d\n", a, b, h, i) ./a In
B - w, j, k, h, i 4206640, 1, 2, 6, 10 In A - x,
y, i, j, h 2280676, 2280672, 1.100000, 2.200000,
6 In Main a, b, h, i 3, 2, 6, 10
Pass by Value
Pass by Reference
15Pass by Value-Results
Pass by value at the time of the call and/or copy
the result back to the argument at the end of the
call also called copy-in-copy-out.
Pass by Name
Textually substitute the argument for every
instance of its corresponding parameter in the
function body. Originated with Algol 60 (Jensens
device), but was dropped by Algols successors --
Pascal, Ada, Modula. Exemplifies late
binding, since evaluation of the argument is
delayed until its occurrence in the function body
is actually executed. Associated with lazy
evaluation in functional languages (e.g.,
Haskell).
real procedure Sum(j, lo, hi, Ej) value lo, hi
integer j, lo, hi real Ej begin real S S
0 for j lo step 1 until hi do S S
Ej Sum S end
xjj
16Recursive Functions Exemplified by foldr in lisp
(letrec ((f (lambda (l) (if (null? l) '()
(cons (car l) (f (cdr l))))))) (f '(1 2 3 4 5
6))) '(1 2 3 4 5 6) (letrec ((f (lambda (v l)
(if (null? l) v (cons (car l) (f v (cdr
l))))))) (f '() '(1 2 3 4 5 6))) '(1 2 3 4 5
6) (letrec ((f (lambda (f1 v l) (if (null? l)
v (f1 (car l) (f f1 v (cdr l))))))) (f
cons '() '(1 2 3 4 5 6))) '(1 2 3 4 5 6) f
foldr If f1 cons, foldr is the identity
function for a list. Its the same as (cons 1
(cons 2 (cons 3( cons 4 (cons 5 (cons 6 '()))))))
(cons 1 (cons 2 (cons 3 (cons 4 (cons
5 (cons 5 '()))))))
(cons 1 (cons 2 (cons 3 (cons 4 (cons
5 (cons 5 '()))))))
This can be thought of as a stack with conss on
it.
Here the stack is upside down
17Recursive Functions Exemplified by foldl in lisp
(letrec ((f (lambda (f1 v l) (if (null? l)
v (f f1 (car l) (cdr l)))))) (f cons '() '(1
2 3 4 5 6))) 6 (letrec ((f (lambda (f1 v l) (if
(null? l) v (f f1 (f1 (car l) v) (cdr
l)))))) (f cons '() '(1 2 3 4 5 6))) '(6 5 4 3 2
1) f foldl If f1 cons, foldl reverses the
list. foldl is tail-recursive because nothing
goes on the stack. Its the same as (cons 6 (cons
5 (cons 4 ( cons 3 (cons 2 (cons 1 '()))))))
Nothing goes on the stack in this case.
18Recursive Functions
cat test.c int factorial (int n) int i
if (n lt 2) printf("factorial returning
1\n") return 1 else i
n factorial(n-1) printf("factorial
returning d\n", i) return i int
main() printf("factorial(3) returns d\n",
factorial(3)) ./a factorial returning
1 factorial returning 2 factorial returning
6 factorial(3) returns 6
A function that can call itself, either directly
or indirectly, is a recursive function.
19Runtime Stack
- A stack of activation records
- An activation record is a block of information
associated with each function call, which
includes - parameters and local variables
- Return address
- Each new call pushes an activation record, and
each completing call pops the topmost one. - So, the topmost record is the most recent call,
and the stack has all active calls at any
run-time moment.
20Runtime Stack for Functions Program
int h, i void B(int w) int j, k
i 2w w w1 void A(int x, int y)
bool i, j B(h) int main()
int a, b h 5 a 3 b 2
A(a, b)
- parameters and local variables
- Return address
- Saved registers
- Temporary variables
- Return value
21Hmm Runtime Stack for Factorial 3
Calling function factorial BasePtr 3, printing
runtime stack null null n 3 null null answer
null number 3 Calling function
factorial BasePtr 5, printing runtime
stack null null n 2 null null n 3 null
null answer null number 3 Calling function
factorial BasePtr 7, printing runtime
stack null null n 1 null null n 2 null
null n 3 null null answer null number
3 Calling function factorial BasePtr 9,
printing runtime stack null null n 0 null
null n 1 null null n 2 null null n 3 null
null answer null number 3
Exiting function factorial BasePtr 9, printing
runtime stack null null n 0 returnfactorial
1 n 1 null null n 2 null null n 3 null
null answer null number 3 Exiting
function factorial BasePtr 7, printing runtime
stack returnfactorial 1 n 1 returnfactorial
1 n 2 null null n 3 null null answer
null number 3 Exiting function
factorial BasePtr 5, printing runtime
stack returnfactorial 1 n 2 returnfactorial
2 n 3 null null answer null number 3
Exiting function factorial BasePtr 3,
printing runtime stack returnfactorial 2 n
3 returnfactorial 6 answer null number 3
int factorial(int n) if(n lt 1)
return 1 else return n
factorial(n - 1) int main() int
number, answer number 3 answer
factorial(number) print(answer)