05 Functions

advertisement
Functions and Recursion
Dr. Philip Cannata
1
10
High Level
Languages
Java (Object Oriented)
This Course
Jython in Java
Relation
ASP
RDF (Horn Clause Deduction,
Semantic Web)
Dr. Philip Cannata
2
“let” 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)
Dr. Philip Cannata
3
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:
> (parse '(with (f (fun (x) x)) 5))
(app (fun 'f (num 5)) (fun 'x (id 'x)))
> (interp (parse '(with (f (fun (x) x)) 5)) (mtSub))
(numV 5)
> (parse '(with (f (fun (x) x)) (f 5)))
(app (fun 'f (app (id 'f) (num 5))) (fun 'x (id 'x)))
> (interp (parse '(with (f (fun (x) x)) (f 5))) (mtSub))
(numV 5)
> (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)))
> (interp (parse '(with (f (fun (x) x)) ((fun (y) (+ y 2)) 5))) (mtSub))
(numV 7)
Dr. Philip Cannata
4
Static 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))))))
Dr. Philip Cannata
5
PLAI 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
Page
27 - "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.
Dr. Philip Cannata
6
$ 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
Dr. Philip Cannata
7
In 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
Dr. Philip Cannata
8
(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.
Dr. Philip Cannata
9
(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:
Result: 22
i: 22
Evaluating: (- x (+ y z))
z: 17
Environment:
Result: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
i: 22
Evaluating: (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x) i))))
y: 22
Environment:
z: 17
i: 22
x: 0
a: 5
Evaluating: (+ y z)
z: 3
Environment:
x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
i: 22
Evaluating: (x z (x 0 ((\ (x) x) i)))
y: 22
Environment:
z: 17
i: 22
x: 0
a: 5
Result: 39
z: 10
Result: -39
x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
Result: -39
Evaluating: (x 0 ((\ (x) x) i))
Evaluating: (- x (+ y z))
Environment:
Environment:
i: 22
i: 22
a: 5
y: -39
z: 10
z: 17
x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
x: 10
Evaluating: ((\ (x) x) i)
Evaluating: (+ y z)
Environment:
Environment:
i: 22
i: 22
a: 5
y: -39
z: 10
z: 17
x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
x: 10
Evaluating: (\ (x) x)
Result: -22
Environment:
Result: 32
i: 22
Result: 32
a: 5
Result: 32
z: 10
Result: 32
x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]
Result: 32
Result: (\ (x) x) [i: 22, a: 5, z: 10, x: (\ (x y) (- x (+ y z)))]
Dr. Philip Cannata
10
10
High Level
Languages
Java (Object Oriented)
This Course
Jython in Java
Relation
ASP
RDF (Horn Clause Deduction,
Semantic Web)
Dr. Philip Cannata
11
Parameter 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.
Dr. Philip Cannata
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);
}
12
Parameter 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 doesn’t normally allow the called
function to modify an argument’s 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 argument’s value.
• By value-result
• By name
Dr. Philip Cannata
13
int h, i;
Pass by Value
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);
}
int h, i;
Pass by Reference
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: 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
$ ./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
14
Dr. Philip Cannata
Pass 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 (Jensen’s device), but was dropped by Algol’s
successors -- Pascal, Ada, Modula.
real procedure Sum(j, lo, hi, Ej);
x[j]*j
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;
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).
Dr. Philip Cannata
15
Recursive Functions Exemplified by foldr in lisp
(letrec ((f (lambda (l) (if (null? l)
(cons 1 || (cons 2 || (cons 3 || (cons 4 || (cons 5 || (cons 5 '()))))))
'(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.
It‘s the same as
(cons 1 (cons 2 (cons 3( cons 4 (cons 5 (cons 6 '()))))))
Here the stack is upside down
Dr. Philip Cannata
(cons (car l) (f (cdr l))))))) (f '(1 2 3 4 5 6)))
(cons 1 || (cons 2 || (cons 3 || (cons 4 || (cons 5 || (cons 5 '()))))))
This can be thought of as a stack with “cons”s on it.
'()
16
Recursive 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
Nothing goes on the stack in this case.
(letrec ((f (lambda (f1 v l) (if (null? l)
Dr. Philip Cannata
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.
It‘s the same as
(cons 6 (cons 5 (cons 4 ( cons 3 (cons 2 (cons 1 '()))))))
17
Recursive Functions
A function that can call itself,
either directly or indirectly, is
a recursive function.
$ cat test.c
int factorial (int n) {
int i;
if (n < 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
Dr. Philip Cannata
18
Runtime 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.
Dr. Philip Cannata
19
Runtime Stack for Functions Program
int h, i;
void B(int w) {
int j, k;
i = 2*w;
w = w+1;
}
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);
}
Dr. Philip Cannata
•
parameters and local variables
•
Return address
•
Saved registers
•
Temporary variables
•
Return value
20
Hmm 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
Dr. Philip Cannata
int factorial(int n) {
if(n < 1) {
return 1;
}
else
{
return n * factorial(n - 1);
}
}
int main() {
int number, answer;
number = 3;
answer = factorial(number);
print(answer);
}
Exiting function: factorial
BasePtr = 9, printing runtime stack
null: null
n: 0
return#factorial: 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
return#factorial: 1
n: 1
return#factorial: 1
n: 2
null: null
n: 3
null: null
answer: null
number: 3
Exiting function: factorial
BasePtr = 5, printing runtime stack
return#factorial: 1
n: 2
return#factorial: 2
n: 3
null: null
answer: null
number: 3
Exiting function: factorial
BasePtr = 3, printing runtime stack
return#factorial: 2
n: 3
return#factorial: 6
answer: null
number: 3
21
Download