Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Programming Languages Lecture 5 Scheme, Subroutines and Control Abstractions.

Similar presentations


Presentation on theme: "1 Programming Languages Lecture 5 Scheme, Subroutines and Control Abstractions."— Presentation transcript:

1 1 Programming Languages Lecture 5 Scheme, Subroutines and Control Abstractions

2 2 Parameter Passing Definition: foo(int x, int y) ; Definition: foo(int x, int y) ; x and y are formal parameters x and y are formal parameters Application: foo(a, b); Application: foo(a, b); a and b are actual parameters or arguments a and b are actual parameters or arguments Parameter Passing Modes Parameter Passing Modes By Value By Value By Reference By Reference By Name By Name By Copy-In / Copy-Out By Copy-In / Copy-Out

3 3 Pass by Value Formal parameter is bound to a Value Formal parameter is bound to a Value Value on stack may be: Value on stack may be: a copy of another value a copy of another value foo (x); the result of an expression the result of an expression foo (x + 1); Easy to implement Easy to implement May require copying large amounts of data May require copying large amounts of data Which can sometimes be avoided with lazy copy Which can sometimes be avoided with lazy copy

4 4 Pass by Reference Formal parameter is bound to a location Formal parameter is bound to a location Value on stack is a pointer to the actual value Value on stack is a pointer to the actual value Avoids making a copy of the argument Avoids making a copy of the argument Allows the procedure to modify the value of its parameters (But only if the actual parameter is an l-value) Allows the procedure to modify the value of its parameters (But only if the actual parameter is an l-value)

5 5 Pass by Name Pass by name – Algol 60 Pass by name – Algol 60 Actual parameters are (re)evaluated each time they are used Actual parameters are (re)evaluated each time they are used Similar to treating parameters as macros Similar to treating parameters as macros Value on stack is a “thunk”, a hidden function that evaluates the actual parameter. Value on stack is a “thunk”, a hidden function that evaluates the actual parameter. Expensive to implement and error prone. Expensive to implement and error prone. No longer used – Mainly of historical interest No longer used – Mainly of historical interest

6 6 Copy-In/Copy-Out Subroutine can modify its parameters Subroutine can modify its parameters Both the value and address are placed on the stack Both the value and address are placed on the stack The local value is used for computation then written back to the original variable when the function returns The local value is used for computation then written back to the original variable when the function returns Addresses Aliasing Issues Addresses Aliasing Issues void foo(int x, int y){ void foo(int x, int y){ x = 7; x = 7; y = y + 2; } y = y + 2; } int main(){ int main(){ int j = 3; int j = 3; foo(j, j);  Alias, x and y refer to same object foo(j, j);  Alias, x and y refer to same object print(j); } print(j); }

7 7 Parameters in ADA In out parameters in Ada In out parameters in Ada function foo (in a : Integer) returns Integer; procedure foo (in a: Integer, out b:Integer); Procedure foo (in out a:Integer); Functions can only have in parameters Functions can only have in parameters Scalars passed by copy-in/copy-out Scalars passed by copy-in/copy-out Tagged arrays, tasks, etc. passed by reference Tagged arrays, tasks, etc. passed by reference Arrays and records implementation dependent Arrays and records implementation dependent Named Parameters Named Parameters foo (a=>1); Parameters with default values Parameters with default values function Incr (base: integer; delt: integer := 1) return integer;

8 8 Parameter passing in C C: parameter passing by value, no semantic checks. Assignment to formal is assignment to local copy C: parameter passing by value, no semantic checks. Assignment to formal is assignment to local copy If argument is pointer, effect is similar to passing designated object by reference If argument is pointer, effect is similar to passing designated object by reference void incr (int* x) { (*x) ++; } void incr (int* x) { (*x) ++; } incr (&counter); /* pointer to counter*/ incr (&counter); /* pointer to counter*/ no need to distinguish between functions and procedures: void indicates side-effects only. no need to distinguish between functions and procedures: void indicates side-effects only.

9 9 Parameter-passing in C++ Default is by-value (same semantics as C) Default is by-value (same semantics as C) Explicit reference parameters: Explicit reference parameters: void incr (int& y) { y++}; void incr (int& y) { y++}; incr (counter); incr (counter); // compiler knows profile of incr, builds reference // compiler knows profile of incr, builds reference semantic intent indicated by qualifier: semantic intent indicated by qualifier: void f (const double& val); void f (const double& val); // in-parameter by reference: call cannot modify it // in-parameter by reference: call cannot modify it

10 10 Parameter-passing in Java Parameters passed by value Parameters passed by value Semantics differs for primitive types and for classes: Semantics differs for primitive types and for classes: primitive types have value semantics primitive types have value semantics objects have reference semantics objects have reference semantics Consequence: methods can modify objects. Consequence: methods can modify objects. No way to express semantic intent on primitive types: assignment allowed, affects local copy. No way to express semantic intent on primitive types: assignment allowed, affects local copy.

11 11 Parameter-passing in Functional Languages Strictly Functional languages have no variables and no assignment, so… Strictly Functional languages have no variables and no assignment, so… Always use pass by value semantics Always use pass by value semantics Implementation may use references for efficiency Implementation may use references for efficiency Procedure can never modify arguments Procedure can never modify arguments Remember, copying the actual parameter value to the formal is initialization, not assignment Remember, copying the actual parameter value to the formal is initialization, not assignment

12 12 Aliasing var var global : integer := 10; global : integer := 10; another : integer := 2; another : integer := 2; procedure confuse ( var first, second : integer); procedure confuse ( var first, second : integer); begin begin first := first + global; first := first + global; second := first * second; second := first * second; end; end;begin confuse (global, another); first and global will be aliased confuse (global, another); first and global will be aliased Semantics should not depend on implementation of parameter passing Semantics should not depend on implementation of parameter passing passing by value with copy-return is less error-prone passing by value with copy-return is less error-prone

13 13 Run-time organization Each subprogram invocation creates an activation record. Each subprogram invocation creates an activation record. Recursion imposes stack allocation (all languages today) Recursion imposes stack allocation (all languages today) Activation record hold actuals, linkage information, saved registers, local entities. Activation record hold actuals, linkage information, saved registers, local entities. caller: place actuals on stack, return address, linkage information, then transfer control to callee. caller: place actuals on stack, return address, linkage information, then transfer control to callee. Prologue: save registers, allocate space for locals Prologue: save registers, allocate space for locals Epilogue: place return value in register or stack position, update actuals, restore registers, then transfer control to caller. Epilogue: place return value in register or stack position, update actuals, restore registers, then transfer control to caller. Binding of locations: actuals and locals are at fixed offsets from frame pointers Binding of locations: actuals and locals are at fixed offsets from frame pointers complications: variable no. of actuals, dynamic objects. complications: variable no. of actuals, dynamic objects.

14 14 Activation record layout actual Return addr Save area Frame pointer Stack pointer local Handled by callee Handled by caller

15 15 Functions with variable number of parameters printf (“this is %d a format %d string”, x, y); printf (“this is %d a format %d string”, x, y); within body of printf, need to locate as many actuals as place- holders in the format string. within body of printf, need to locate as many actuals as place- holders in the format string. Solution: place parameters on stack in reverse order. Actuals at positive offset from FP, locals at negative offset from FP. Solution: place parameters on stack in reverse order. Actuals at positive offset from FP, locals at negative offset from FP. actual n actual n actual n-1 actual n-1 … actual 1 (format string) actual 1 (format string) return address return address

16 16 Objects of dynamic size declare declare x : string (1..N); -- N global, non-constant x : string (1..N); -- N global, non-constant y : string (1..N); y : string (1..N); begin... begin... where is the start of y in the activation record? where is the start of y in the activation record? Solution 1: use indirection: activation record hold pointers. Simpler implementation, costly dynamic allocation., deallocation. Solution 1: use indirection: activation record hold pointers. Simpler implementation, costly dynamic allocation., deallocation. solution 2: local indirection: activation record holds offset into stack. solution 2: local indirection: activation record holds offset into stack. Faster allocation/deallocation, complex implementation. Faster allocation/deallocation, complex implementation.

17 17 Global linkage Static chain: pointer to activation record of statically enclosing scope Static chain: pointer to activation record of statically enclosing scope Display: array of pointers to activation records Display: array of pointers to activation records does not work for function values does not work for function values functional languages allocate activation records on heap functional languages allocate activation records on heap may not work for pointers to functions may not work for pointers to functions simpler if there is no nesting (C, C++, Java) simpler if there is no nesting (C, C++, Java) can check static legality in many cases (Ada) can check static legality in many cases (Ada)

18 18 Static Links Activation record hold pointer to activation record of enclosing scope. Setup as part of call prologue. Activation record hold pointer to activation record of enclosing scope. Setup as part of call prologue. outer inner To enclosing scope To retrieve entity 3 frames out: 3 dereference operations

19 19 Display Global array of pointers to current activation records Global array of pointers to current activation records outer inner display outermost... To retrieve entity 3 frames out: one indexing operation

20 20 Subprogram parameters Caller can see parameter, therefore environment of parameter is subset of current environment Parameter is pair (ptr to code, Env) Caller can see parameter, therefore environment of parameter is subset of current environment Parameter is pair (ptr to code, Env) type proc is access procedure (X : Integer); type proc is access procedure (X : Integer); procedure Use_It (Helper : proc); procedure Use_It (Helper : proc); procedure Do_It (X : Integer) is … procedure Do_It (X : Integer) is … Use_It (Do_It’Access); Use_It (Do_It’Access); -- ‘Access creates pair (ptr to Do_It, environment of Do_It) -- ‘Access creates pair (ptr to Do_It, environment of Do_It) simplest implementation if Env is pointer (static link) simplest implementation if Env is pointer (static link) Display more efficient to retrieve non-local entities, less efficient for subprogram parameters. Display more efficient to retrieve non-local entities, less efficient for subprogram parameters.

21 21 Subprogram parameters in C/C++ void (*pf) (string); void (*pf) (string); // pf is a pointer to a function that takes a string argument and returns nothing (void). // pf is a pointer to a function that takes a string argument and returns nothing (void). typedef void (*PROC)(int); typedef void (*PROC)(int); // type abbreviation clarifies syntax // type abbreviation clarifies syntax void use_it (PROC); void use_it (PROC); PROC ptr = &do_it; PROC ptr = &do_it; use_it (ptr); use_it (ptr); use_it (&do_it); use_it (&do_it);

22 22 Subprogram parameters in Java No notion of pointer, so no immediate translation No notion of pointer, so no immediate translation Dynamic dispatching on a virtual method is indirect call, so can be obtained using interfaces, classes, and extensions Dynamic dispatching on a virtual method is indirect call, so can be obtained using interfaces, classes, and extensions Subprograms must be wrapped in classes, e.g. Comparator, etc. Subprograms must be wrapped in classes, e.g. Comparator, etc.

23 23 The limits of stack allocation type ptr is access function (x : integer) return integer; type ptr is access function (x : integer) return integer; function make_incr (x : integer) return ptr is function make_incr (x : integer) return ptr is function new_incr (base : integer) return integer is function new_incr (base : integer) return integer is begin begin return base + x; -- reference to formal of make_incr return base + x; -- reference to formal of make_incr end; end; begin begin return new_incr’access; -- will it work? return new_incr’access; -- will it work? end; end; add_five: ptr := make_incr (5); add_five: ptr := make_incr (5); total : integer := add_five (10); -- where does add_five find x ? total : integer := add_five (10); -- where does add_five find x ?

24 24 Heap allocation of activation record General implementation of First-Order functions requires that the environment of definition of the function must be preserved until the point of call: activation record cannot be reclaimed if it creates functions. General implementation of First-Order functions requires that the environment of definition of the function must be preserved until the point of call: activation record cannot be reclaimed if it creates functions. Functional languages require more complex run-time management. Functional languages require more complex run-time management. Higher-order functions: functions that return (build) functions, are powerful but complex mechanisms. Imperative languages restrict their use. Higher-order functions: functions that return (build) functions, are powerful but complex mechanisms. Imperative languages restrict their use. A function that returns a pointer to a function is a higher-order function. A function that returns a pointer to a function is a higher-order function.

25 25 Higher-order functions Both arguments and result can be (pointers to) subprograms: Both arguments and result can be (pointers to) subprograms: type Func is access function (x : integer) return integer; type Func is access function (x : integer) return integer; function compose (first, second : Func) return Func is function compose (first, second : Func) return Func is begin begin function result (x : integer) return integer is function result (x : integer) return integer is begin begin return (second (first (x)); -- implicit dereference on call return (second (first (x)); -- implicit dereference on call end; -- in C++ as well. end; -- in C++ as well. begin begin return result ’access; -- but first and second won’t exist at the point return result ’access; -- but first and second won’t exist at the point end; -- of call, so illegal in Ada. end; -- of call, so illegal in Ada.

26 26 Restricting higher-order functions C: no nested definitions, so environment is always global. C: no nested definitions, so environment is always global. C++: ditto, except for nested classes. C++: ditto, except for nested classes. Ada: static checks to reject possible dangling references Ada: static checks to reject possible dangling references Modula: pointers to function illegal if function not declared at top-level. Modula: pointers to function illegal if function not declared at top-level. LISP: special syntax to indicate capture of environment LISP: special syntax to indicate capture of environment ML, Haskell: no restriction: compose is a primitive ML, Haskell: no restriction: compose is a primitive

27 27 Returning composite values Intermediate problem: functions that return values of non-static sizes: Intermediate problem: functions that return values of non-static sizes: function conc3 (x, y, z : string) return string is function conc3 (x, y, z : string) return string is begin begin return x & “:” & y & “:” & z; return x & “:” & y & “:” & z; end; end; example : string := conc3 (this, that, theother); example : string := conc3 (this, that, theother); best not to use heap explicitly, but still need indirection. best not to use heap explicitly, but still need indirection. Simplest : forbid it (Pascal, C) or use heap automatically (Java) Simplest : forbid it (Pascal, C) or use heap automatically (Java)

28 28 Evaluation Order “Normal Order” (Lazy) Evaluation – Haskell “Normal Order” (Lazy) Evaluation – Haskell Arguments are not evaluated unless and until they are actually needed Arguments are not evaluated unless and until they are actually needed Allows functions that define infinite lists! Allows functions that define infinite lists! (define naturals (letrec ((next n) (cons n (delay (next (+ n 1))))))) (next 1))) (letrec ((next n) (cons n (delay (next (+ n 1))))))) (next 1))) (define head car) (define (tail stream) (force (cdr stream)))) Scheme uses delay and force to do lazy evaluation Scheme uses delay and force to do lazy evaluation Applicative Order Evaluation Applicative Order Evaluation Arguments are evaluated prior to execution of the function, whether they will be needed or not. Arguments are evaluated prior to execution of the function, whether they will be needed or not.

29 29 Lambda Calculus Developed by Alonzo Church in 1930’s to examine formal properties of computability Developed by Alonzo Church in 1930’s to examine formal properties of computability Function Definition: x.M Function Definition: x.M x is the formal parameter x is the formal parameter M is an expression on x M is an expression on x Function Application Function Application x.M N x.M N Examples Examples x.x – identity x.x – identity x.times x x – square x.times x x – square x. y.sqrt (+ (square x) (square y)) x. y.sqrt (+ (square x) (square y))

30 30 Lambda Calculus Substitutions Alpha (  ) reduction – renaming Alpha (  ) reduction – renaming x.E   y.E substituting y for x x.E   y.E substituting y for x Beta (  ) reduction – application Beta (  ) reduction – application ( x.E) M   E substituting M for x ( x.E) M   E substituting M for x Similar to call by name Similar to call by name Eta (  ) reduction – simplifying Eta (  ) reduction – simplifying x.F x   F – unnecessary expression x.F x   F – unnecessary expression

31 31 Theoretical Foundation Church-Turing Thesis Church-Turing Thesis Effective computation Effective computation Turing machines and -calculus Turing machines and -calculus Church-Rosser Theorems for -calculus Church-Rosser Theorems for -calculus If reductions produce terminal form (no further reduction possible) that form is unique. If reductions produce terminal form (no further reduction possible) that form is unique. If any evaluation order will terminate, normal order will terminate. If any evaluation order will terminate, normal order will terminate.

32 32 Introduction to Scheme Dialect of Lisp Developed by Guy Steele (who is also one of the original developers of Java) and Gerald Sussman Dialect of Lisp Developed by Guy Steele (who is also one of the original developers of Java) and Gerald Sussman Based on Lambda Calculus Based on Lambda Calculus Static scope rules Static scope rules Dynamically typed Dynamically typed Continuations Continuations First class functions First class functions

33 33 Scheme Resources List of scheme resources: http://www.swiss.ai.mit.edu/projects/scheme/ List of scheme resources: http://www.swiss.ai.mit.edu/projects/scheme/ http://www.swiss.ai.mit.edu/projects/scheme/ Download MIT Scheme Download MIT Scheme http://www.gnu.org/software/mit-scheme/ http://www.gnu.org/software/mit-scheme/http://www.gnu.org/software/mit-scheme/ Books: Books: The Little Schemer, by Daniel P. Friedman, Matthias Felleisen The Little Schemer, by Daniel P. Friedman, Matthias Felleisen Structure and Implementation of Computer Programs, by Harold Abelson and Gerald Sussman (full-text available on-line) Structure and Implementation of Computer Programs, by Harold Abelson and Gerald Sussman (full-text available on-line)full-text available on-linefull-text available on-line

34 34 Basic Scheme Syntax A Scheme program is a list A Scheme program is a list ( …) ( …) First element of list is a function over the other elements First element of list is a function over the other elements (+ 2 2) is 4 (+ 2 2) is 4 An element may be a list An element may be a list (+ 2 (* 2 3)) is 8 (+ 2 (* 2 3)) is 8 Function definitions introduced by “lambda” Function definitions introduced by “lambda” (“lambda” ) (“lambda” ) (lambda (x) (+ x x)) – a procedure (lambda (x) (+ x x)) – a procedure ((lambda (x) (+ x x)) 4) – a value, 8 ((lambda (x) (+ x x)) 4) – a value, 8

35 35 Scheme Example ; semicolon starts a comment (define fact ; binds “fact” to the definition (lambda (n) (lambda (n) (if (= n 0) (if (= n 0) 1 ; base case 1 ; base case (* n (fact (- n 1)))))) (* n (fact (- n 1)))))) (define (fact n) (if …)) ; shorthand for the above

36 36 Quote If every list is a computation, how do we describe data? If every list is a computation, how do we describe data? Another primitive: quote Another primitive: quote (quote (1 2 3 4)) (quote (1 2 3 4)) => (1 2 3 4) => (1 2 3 4) (quote (this is a simple declarative sentence) (quote (this is a simple declarative sentence) => (this is a simple declarative sentence) => (this is a simple declarative sentence) ‘ (this also works) ‘ (this also works) => (this also works) => (this also works)

37 37 Car and Cdr Names are historical Names are historical car – contents of address register car – contents of address register cdr – contents of data register cdr – contents of data register car = head ; first element car = head ; first element cdr = tail; rest of list cdr = tail; rest of list cadar = (head (tail (head x))) cadar = (head (tail (head x))) cddar = (head (tail (tail x))) ; 3 rd element cddar = (head (tail (tail x))) ; 3 rd element

38 38 Decomposing a list (car ‘(this is a list of symbols)) (car ‘(this is a list of symbols)) => this => this (cdr ‘(this is a list of symbols)) (cdr ‘(this is a list of symbols)) => (is a list of symbols) => (is a list of symbols) (cdr ‘(this that)) (cdr ‘(this that)) => (that) ; a list => (that) ; a list (cdr ‘(singleton)) (cdr ‘(singleton)) => () ; the empty list => () ; the empty list (car ‘()) ; run time error (car ‘()) ; run time error

39 39 Building lists (cons ‘this ‘(that and the other)) (cons ‘this ‘(that and the other)) => (this that and the other) => (this that and the other) (cons ‘a ‘()) (cons ‘a ‘()) => (a) => (a) useful shortcut: list useful shortcut: list (list ‘a ‘b ‘c ‘d ‘e) (list ‘a ‘b ‘c ‘d ‘e) => (a b c d e) => (a b c d e) equivalent to equivalent to (cons ‘a (cons ‘b (cons ‘c (cons ‘d (cons ‘e ‘()))))) (cons ‘a (cons ‘b (cons ‘c (cons ‘d (cons ‘e ‘())))))

40 40 Control structures Conditional Conditional (if condition expr1 expr2) (if condition expr1 expr2) Generalized form Generalized form (cond (cond (pred1 expr1) (pred1 expr1) (pred2 expr2) (pred2 expr2) … (else exprn) (else exprn) Needs special rule: evaluate only the successful entry if and cond are not regular functions

41 41 Function declarations (define (sqr n) (* n n)) (define (sqr n) (* n n)) define is also special: body is not evaluated define is also special: body is not evaluated defines produces a binding: sqr is bound to the body of the computation: defines produces a binding: sqr is bound to the body of the computation: (lambda (n) (* n n)) (lambda (n) (* n n)) define can produce value bindings as well: define can produce value bindings as well: (define x 15) (define x 15) (sqr x) (sqr x) => 225 => 225

42 42 Recursion (define (add1 x) (+ x 1)) ; the beginnings of Peano arithmetic (define (add1 x) (+ x 1)) ; the beginnings of Peano arithmetic (define (sub1 x) (- x 1)) (define (sub1 x) (- x 1)) (define (add x y) (define (add x y) (if (= y 0) x (if (= y 0) x (add ( (add1 x) (sub1 y)))) (add ( (add1 x) (sub1 y)))) (define (times x y) (define (times x y) (cond (cond ((= y 0) 0) ((= y 0) 0) ((= y 1) x) ((= y 1) x) (else (add x (times (x (sub1 y))))))) (else (add x (times (x (sub1 y)))))))

43 43 Recursion (ii) (define (exp x y) (define (exp x y) (cond (cond ((eq y 0) 1) ((eq y 0) 1) (else (times x (exp x (sub1 y)))))) (else (times x (exp x (sub1 y)))))) better: (define (fast-exp x y) (define (fast-exp x y) (cond (= y 0) 1) (cond (= y 0) 1) ( (even? y) (square (fast-exp x (/ y 2)))) ( (even? y) (square (fast-exp x (/ y 2)))) (else (* x (fast-exp x (- y 1)))))) (else (* x (fast-exp x (- y 1)))))) (define (even? n) (= (remainder n 2) 0)) ; defining a predicate (define (even? n) (= (remainder n 2) 0)) ; defining a predicate

44 44 Recursion on lists (define (member elmt lis) (define (member elmt lis) (cond (cond ((null? lis) ‘()) ((null? lis) ‘()) ((eq elmt (car lis)) lis) ((eq elmt (car lis)) lis) (else (member elmt (cdr lis))))) (else (member elmt (cdr lis))))) convention: return rest of list, starting from elmt, rather than #t or #f convention: every non-false value is true in a boolean context

45 45 Predicates If variables are untyped, need run-time tests to determine kind: If variables are untyped, need run-time tests to determine kind: symbol? symbol? number? number? list? list? null? null? zero? zero? Syntax conventions differ in different dialects: symbolp, numberp, listp, zerop...

46 46 Functional arguments (define (map fun lis) (define (map fun lis) (cond (cond ((null? lis) ‘()) ((null? lis) ‘()) (cons (fun (car lis)) (map fun (cdr lis))))) (cons (fun (car lis)) (map fun (cdr lis))))) (map sqr (map sqr ‘( 1 2 3 4)) (map sqr (map sqr ‘( 1 2 3 4)) => (1 16 81 256) => (1 16 81 256)

47 47 Self-definition (define (eval exp env) ; the lisp interpreter (define (eval exp env) ; the lisp interpreter (cond (cond ((number? exp) exp) ; numbers are self-evaluating ((number? exp) exp) ; numbers are self-evaluating ((symbol? exp) (lookup exp env)) ; a symbol has a binding ((symbol? exp) (lookup exp env)) ; a symbol has a binding ((null? exp) ‘()) ((null? exp) ‘()) ((eq (car exp) ‘quote) (car (cdr exp))) ; could write cadr ((eq (car exp) ‘quote) (car (cdr exp))) ; could write cadr ((eq (car exp) ‘car) (car (car (cdr exp)))) ; caadr ((eq (car exp) ‘car) (car (car (cdr exp)))) ; caadr ((eq (car exp) ‘cdr) (cdr (car (cdr exp)))) : cdadr ((eq (car exp) ‘cdr) (cdr (car (cdr exp)))) : cdadr (else (apply (eval (car exp) env) ; apply function (else (apply (eval (car exp) env) ; apply function (eval-list (cdr exp) env))) ; to arguments (eval-list (cdr exp) env))) ; to arguments

48 48 Function application (define (apply procedure arguments) (define (apply procedure arguments) (eval (procedure-body procedure) (eval (procedure-body procedure) (extend-environment (extend-environment (parameters procedure) (parameters procedure) arguments arguments (environment procedure)))) (environment procedure)))) In words: add actuals to environment, evaluate body of procedure in new environment Note: environment is in of procedure definition (closure)

49 49 Environments An environment describes the current bindings of symbols An environment describes the current bindings of symbols A binding is a pair: (symbol value) A binding is a pair: (symbol value) A frame is a list of bindings (activation record), i.e. an association list: ((s1 v1) (s2 v2)…) A frame is a list of bindings (activation record), i.e. an association list: ((s1 v1) (s2 v2)…) An environment is a list of frames An environment is a list of frames In some cases we can treat the environment as a single association list (e.g. with dynamic binding) In some cases we can treat the environment as a single association list (e.g. with dynamic binding)

50 50 Association lists (define (add-assoc symb val env) (cons (list symb val) env)) ; add a binding (cons (list symb val) env)) ; add a binding (define (name binding) (car binding)) ; for readability (define (value binding) (car (cdr binding))); (define (lookup symb env) ; sequential search (cond (cond ((null? env) ‘()) ; error detected later ((null? env) ‘()) ; error detected later ((eq symb (name (car env))) (value (car env)) ((eq symb (name (car env))) (value (car env)) (else (lookup symb (cdr env))))) (else (lookup symb (cdr env)))))

51 51 Procedures and their environment A function has three components: a list of formals, a body, and environment of definition. Formals and body are represented by a lambda expression: A function has three components: a list of formals, a body, and environment of definition. Formals and body are represented by a lambda expression: (lambda (f1 f2..) expr) (lambda (f1 f2..) expr) A function is evaluated in its environment of definition (lexical scoping) after adding the current bindings of the actuals (activation record) A function is evaluated in its environment of definition (lexical scoping) after adding the current bindings of the actuals (activation record) The definition must capture all three components The definition must capture all three components (define (make-procedure spec body env) (define (make-procedure spec body env) (list ‘procedure (make-lambda spec body) env)) (list ‘procedure (make-lambda spec body) env)) make-procedure is called by eval to evaluate a define

52 52 Procedure components given the representation given the representation (procedure (lambda parameters body) env) (procedure (lambda parameters body) env) the components of a procedure can be obtained as follows: (define (parameters proc) (cadr (cadr proc))) (define (parameters proc) (cadr (cadr proc))) (define (procedure-body proc) (caddr (cadr proc))) (define (procedure-body proc) (caddr (cadr proc))) (define (environment proc) (caddr proc)) (define (environment proc) (caddr proc))

53 53 Evaluating a function definition (define (name binding) (car binding)) (define (name binding) (car binding)) results in the binding: results in the binding: (name (name (procedure (lambda (binding) (car binding)) env)) (procedure (lambda (binding) (car binding)) env)) procedure and lambda are labels to indicate kind procedure and lambda are labels to indicate kind Env is the current environment. At the top level it includes the binding for car (used in the body) as well as all other predefined symbols. Env is the current environment. At the top level it includes the binding for car (used in the body) as well as all other predefined symbols.

54 54 The need for closure (define (compose f1 f2) (define (compose f1 f2) (lambda (x) (f1 (f2 x)))) (lambda (x) (f1 (f2 x)))) (define (sqr x) (* x x)) (define (sqr x) (* x x)) (define fourth (compose (sqr sqr))) (define fourth (compose (sqr sqr))) (fourth 4) ; yields 256 (fourth 4) ; yields 256 When fourth is called, the bindings of f1 and f2 have disappeared. The evaluation of the lambda captures the environment in which f1 and f2 are bound to sqr.

55 55 Tail recursion Tail recursive function needs single stack frame. mandated by semantics of Scheme: Tail recursive function needs single stack frame. mandated by semantics of Scheme: (define (factorial n) (if (zero? N) 1) (define (factorial n) (if (zero? N) 1) (* n (factorial (- n 1))) ; stack grows to size n (* n (factorial (- n 1))) ; stack grows to size n define factorial n) (fact-iter 1 1 n) ; alternate definition define factorial n) (fact-iter 1 1 n) ; alternate definition (define (fact-iter prod count var) (define (fact-iter prod count var) (if (> count var) prod (if (> count var) prod (fact-iter (* count prod) ; tail recursion (fact-iter (* count prod) ; tail recursion (+ count 1) ; implemented as loop (+ count 1) ; implemented as loop var)))) var))))

56 56 Implementation of tail recursion If last operation in function is recursive call, overwrite actuals and go to beginning of code: If last operation in function is recursive call, overwrite actuals and go to beginning of code: (define (last lis) (define (last lis) (if (null? (cdr lis) (car lis)) (if (null? (cdr lis) (car lis)) (last (crd lis)))) ; can be done with loop (last (crd lis)))) ; can be done with loop (define (length lis) (define (length lis) (if (null? lis) 0) (if (null? lis) 0) (+ 1 (length (cdr lis)))) ; not tail recursive! (+ 1 (length (cdr lis)))) ; not tail recursive!


Download ppt "1 Programming Languages Lecture 5 Scheme, Subroutines and Control Abstractions."

Similar presentations


Ads by Google