21
Prof. Fateman CS 164 Lecture 26 1 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Embed Size (px)

Citation preview

Page 1: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 1

Functional Tiger, Calling variations

Lecture 26

Page 2: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 2

Typechecking

DID YOU START ON ASSIGNMENT 5 YET?

Page 3: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 3

Lex Changes to Tiger to make it “functional”

New token, ->

New grammar rules for type declaration ty ! ty -> ty ty ! (ty {,ty}) -> ty Ty ! () -> ty

E.g. let type foo= (int,int) -> int type bar=(int->string,int) -> int->int

Page 4: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 4

Parse Changes to Tiger to make it “functional”

New grammar rules for CallExp exp ! exp (exp {,exp}) ;actually unlikely to be LALR(1)

E.g. Add(3)(4) Where function Add(n:int):int->int = let function z(x:int):int=n+x in zend /* compare to scheme, (define add(n)(lambda(x)(+ x n))… */

Page 5: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 5

AST Changes to Tiger to make it “functional”

New Type, say FunTy added to ArrayTy, RecordTy…

Perhaps new FunExp added to IntExp, etc.

Page 6: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 6

Type Check Changes to Tiger to make it “functional”

New typecheckingfunction Add(n:int):int->int = let function z(x:int):int=n+x /* implicit decl: type z=int->int */ in zEndAnd lots more, checking signatures more carefully,

deciding about structure vs name equivalence again.

(personally, I think this would be a delicate business: to match type bar=(int->string,int) -> int->int)

Page 7: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 7

Interpreter Changes to Tiger to make it “functional”

Our interpreter: Nothing changes.Our environments persist until the Lisp GC

removes them. Lists of bindings can look like

this.

env1

env2

Page 8: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 8

Interpreter Changes to Tiger to make it “functional”

A stack interpreter cannot build such a tree. Its lexical environments persist only while within lexical scope. We need to preserve until function, returned upward, is called. Here env2 clobbers env1.

Another possibility (next slide) is that we exit from some scope but must still access it.

env1env2

Page 9: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 9

Example… of upward functional arg (return)

Let type nilint = ()->int/*type is no args -> int */ function f1():nilint = let function f2()nilint= let function f3():nilint= let var x:=10 function f4():int =x /*this function is returned

*/ in f4 end in f3 end in f2 end in f1() end/* f1() must return 10 so the lexical scope in which x

lives must be saved somehow. */

Page 10: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 10

Interpreter Changes to Tiger to make it “functional”

Let var y:=43 /*not used, though in theory visible in f4 */

function f1():nilint = let function f2():nilint= let function f3():nilint= let var x:=10 /*visible in f4, escapes…*/ function f4():int =x in f4 end in f3 end in f2 end in f1() end/* f4 could be some kind of bundle including x but

not (for example) y, f1, f2, f3. */

Page 11: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 11

Interpreter Changes to Tiger to make it “functional”

Let var y:=43 /* now used and visible in f4 */ function f1():nilint = /*type no args -> int */ let function f2():nilint= let function f3():nilint= let var x:=10 /*visible in f4, escapes…*/ function f4():int =x+y in f4 end in f3 end in f2 end in f1() end/* f4 could be in some kind of bundle or closure

including x and y */

Page 12: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 12

Other suggested changes of chapter 15

• Pure-functional • Call by name• Lazy evaluation

Page 13: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 13

Pure Functional

• no assignments; the only time a variable can take a value is on initialization or parameter passage.

• no input/output; continuation based I/O– getchar() replaced by getchar(consumer)– Consumer is of type string ->answer– E.g getchar(eatchar) CALLS eatcar with a

single-character string.– Continuation based processing is useful in

compiling..We will revisit this idea later; here it is a hack.

Page 14: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 14

Pure Functional; mostly a theoretical construct

• Helpful if you wish to reason about programs– prove equivalence of programs– Lazy evaluation helps avoid equivalence “if

programs halt” p 342, sometimes. Values are computed only when the results actually matter

– Opposite of lazy is “strict”.. All expressions are evaluated as control flow reaches them, whether or not their results are needed.

– Lazy eval vs call-by-need… more later

Page 15: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 15

Call by name (Important on CS GRE)

Invented for Algol 60. Often the same as call by reference.. BUT if Tiger had call-by-name semantics,

Let function Q(a,x)= (x:=3; a:=4) var z:intarray :=array[10] of 0Call Q(z[i],i) /*by name*/ results in setting z[3] to 4. versus…Call Q(m,n) Simply sets n to 3, m to 4. Same as call by ref.Call by name: each value is a thunk that computes its

value or location when used;

Page 16: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 16

One implementation:copy over the body..

Invented for Algol 60. Often the same as call by reference.. BUT if Tiger had call-by-name semantics,

Let function Q(a,x)= (x:=3; a:=4) var z:intarray :=array[10] of 0Call Q(z[i],i) /*by name*/ i:=3; z[i]:=4

An implementation could copy over the function body, renaming as appropriate to avoid “other” conflicts.

(if there were other instances of i and z in Q, they would have to be renamed, e.g. Qi and Qz might do.)

Page 17: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 17

Lazy evaluation

= call by need. Each “thunk” of call-by-name is now 2 cells: the thunk function + the memoized value if it has been visited before.

You’ve seen this in CS61a. …Set up fibonacci function to remember fib(0), fib(1), then compute fib(2)=fib(0)+fib(1) but REMEMBER fib(2). Compute

fib(3)= fib(1)+fib(2) remembered etc.This is potentially an enormous savings in heavily

recursive purely-functional programs. For call-by-name or lazy evaluation, careful compilation can make this efficient.

Page 18: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 18

A thought: should cons evaluate its arguments?

If you make the following arrangements: instead of (cons a b), do (list ‘CONS ‘a ‘b)Instead of (car x) do (if (eq (car x) ‘CONS) (eval (cadr x))) Instead of (cdr x) do(if (eq (car x) ‘CONS) (eval (caddr x)));; really we can’t do (list ‘CONS ‘a ‘b) but need(list ‘CONS (closure of a, environment) (closure of b, environment))

… so we can do (eval a) or (eval b).

Look at it this way. No one knows what’s inside a cons cell without looking at its car or cdr. So don’t compute it until someone looks. Pprint looks..

Page 19: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 19

Tiger function calls

As a practical semantic view, Tiger calls look rather like lisp. Call by value, but all values are refs to objects

The call Foo(x,y,z) cannot change x, y, or z.However, if x is an array, Foo can change x[0], x[1]

… because a pointer to the array x is given to Foo.If y is a string “hello” then y POINTs to “hello”.Within function Foo(a:intarray,b:string,c:int)… a

change to b:= bye merely makes local b POINT to a different string. y still points to “hello”.

Page 20: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 20

Call by value, copy-in/out, etc

Value : imagine all arguments which are simple, are copied over into a space owned by the called program. For example, stack space.

Function foo(a,b,c)= (a:=b+c) changes nothing outside foo.Copy-in/out or call by value/return is

sometimes used (Fortran)– if there are no other “aliased” access routes to variables they are equivalent.

Page 21: Prof. Fateman CS 164 Lecture 261 Functional Tiger, Calling variations Lecture 26

Prof. Fateman CS 164 Lecture 26 21

Call by reference in Fortran

Function foo(a,b,c)= (a:=b+c) //this is not fortran syntax

call foo(3,4,5)Print(3) may result in printing 9.This is not “correct usage” but has

historically happened in common implementations…