CS 234319: Programming Languages Yossi Gil

*

January 31, 2015

* [email protected]

1

6

Imperative programming 6.1 Commands (70 frs.) . . . . . . . . . . . . . . 6.1.1 Commands vs. expressions (16 frs.) . . 6.1.2 Recursive definitions (4 frs.) . . . . . . 6.1.3 Expressions’ evaluation order (6 frs.) . 6.1.4 Atomic commands (12 frs.) . . . . . . 6.1.5 Block commands (11 frs.) . . . . . . . 6.1.6 Conditional commands . . . . . . . . 6.1.7 Iterative commands . . . . . . . . . . 6.1.8 Exercises (7 frs.) . . . . . . . . . . . . 6.2 Structured programming (11 frs.) . . . . . . . 6.3 Sequencers (1 fr.) . . . . . . . . . . . . . . . . 6.4 Exceptions (35 frs.) . . . . . . . . . . . . . . . 6.4.1 Robustness (3 frs.) . . . . . . . . . . . 6.4.2 Policy I: resumption (5 frs.) . . . . . . 6.4.3 Policy II: error rolling (6 frs.) . . . . . 6.4.4 Policy III: setjmp/longmp of C (1 fr.) 6.4.5 Policy IV: exceptions (4 frs.) . . . . . 6.4.6 Kinds of exceptions (8 frs.) . . . . . . 6.4.7 Resource acquisition is (or isn’t) initialization . . . . . . . . . . . . . . . . 6.5 Functional abstractions (102 frs.) . . . . . . . 6.5.1 Closures (37 frs.) . . . . . . . . . . . . 6.5.2 Function objects (12 frs.) . . . . . . . 6.5.3 Generators (11 frs.) . . . . . . . . . . . 6.5.4 Iterators (17 frs.) . . . . . . . . . . . . 6.5.5 Iterator examples (15 frs.) . . . . . . . 6.5.6 Coroutines (10 frs.) . . . . . . . . . . . 6.5.7 Exercises . . . . . . . . . . . . . . . . 1. Imperative programming: mindmap

Commands vs. expressions

6.1.1 Frames:

◊ Commands: what are they?

◊ Commands vs. state-

. . . . . . . . . . . . . . . . . .

2 ments ◊ Commands vs. expressions ◊ Expressions changing the 2 program’s state? ◊ Expressions without side-effects? ◊ “Statement4 expressions” in Gnu-C ◊ and in Mock … ◊ “Commandexpression” ◊ Reasonable realizations of command-expression I 6 ◊ Reasonable realizations of command-expression II 8 2. Commands: what are they? 9 Commands are characteristic of imperative languages1 10 12 Definition 6.1 (Command). A command is a part of a 14 computer program, which: 14 • does not produce a value, 16 17 • whose main purpose is altering the program’s state. 17 • even vacuously 18 19 Examples 20 21 • I/O: print, read,… 21 • Assignment

. . . . . . . . .

22 23 23 30 33 35 38 42 43

• Loops • Conditional • “nop” • “\relax” • “;” 3. Commands vs. statements

a visual

• The misnomer statement is (much) more frequently used in the literature. • But, there is nothing declarative in commands!

Command Expressions

• “Statement” also means:

Expression Oriented Languages Escape

Jump

– definitions – declarations . – ..

Variations

Commands vs.Expressions

Structured vs.Non-Structured Programs NassiShneiderman Diagrams

Commands

Examples – Pascal –C Atomic – Java Commands

– anything ending with a “;”

Basics

Varieties – Definite/Indefinite – Sequential/Simultaneous/Collateral

Iterative

Varieties – Sequential – Simultaneous – Collateral

4. Commands vs. expressions

Skip

Command Constructors

Conditional

Block

Varieties – Sequential – Simultaneous – Collateral

Partial Specification

Varieties Assignment – Vanilla – Update – Multiple – Simultaneous – Collateral

Ideally, they should be distinct Commands • Change state • No value

Figure 6.1: Imperative programming: a visual mindmap

6.1

Expression • No state change

Commands 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8

Commands vs. expressions (10 frs.) . . Recursive definitions (11 frs.) . . . . . Expressions’ evaluation order (16 frs.) Atomic commands (4 frs.) . . . . . . . Block commands (6 frs.) . . . . . . . . Conditional commands (12 frs.) . . . . Iterative commands (11 frs.) . . . . . . Exercises . . . . . . . . . . . . . . . .

• Produce a value . 2 . 4 . 6 . 8 . 9 . 10 . 12 . 14

In practice, the borderline is not so clear

Commands

1 No

2

Expressions

commands in purely functional languages

5. Expressions changing the program’s state?

8. and in Mock …

Nasty CS101 Exam Question You are given a seemingly

innocent Pascal code, and asked…

return if ( (while (*s++ = *t++) ;) > (while (*t++ == *s++) ;) ) 3; else while (*s++ != *t++) return 7;

Procedure Hamlet;

VAR happy: Boolean; Function toBe:Boolean; Begin … happy := not happy; toBe := happy End; Begin … happy := false; If toBe and not toBe WriteLn("The Answer!"); End; Could "The Answer"

Mock

Huh? What does this mean? Is this useful to anyone?

ever be written?

9. “Command-expression”

• Suppose that toBe is a function nested in procedure Hamlet,

Command expressions is an idealistic notion:

• which may have access to a global variable,

• Any expression may be substituted by a command

• whose initial value is false,

• Every command is an expression, so every command returns a value:

• In fact, function toBe returns the value of this global variable,

Atomic atomic commands are expressions

• just after flipping it!

Conditional the selected branch

Sequence the last expression Iteration the last iteration? What if there were no iterations?

• So, the answer is,…

Return What value should “return 3” return?

6. Expressions without side-effects?

What happened here?

10. Reasonable realizations command-expression I

• Expressions do not make sense without function calls

of

• In “Statement-Expressions” of Gnu-C

• Functions may invoke commands

• ML, in with the semicolon, “;” operator:

• Commands, by definition, alter the program state!

– takes 2 operands

• Worse, in some PLs, certain operators have side-effects

– computes the 1st operand…

Would it be possible to prevent side-effects at the PL design level?

– and then discards it! – computes the 2nd operand…

• Representation of state?

– and then returns it.

ML

• How would you do I/O?

Standard ML of New Jersey … - (1;2)*(3;4); val it = 8 : int

• In general, tough, but awkward Obvious example, pure-ML

• The ancient BCPL

7. “Statement-expressions” in Gnu-C

An excerpt from Section 6.1 Statements and Declarations in Expressions of Chapter 6 Extensions to the C Language Family of the Gnu-C manual:

11. Reasonable realizations command-expression II

of

• PostScript

Gun-C

({ int y = foo (); int z; if (y > 0) z = y; else z = - y; z; })

• Icon, in which every expression is a generator; – atomic expressions are things such as values, which can only yield one value;

is a valid (though slightly more complex than necessary) expression for the absolute value of foo().

– iterations return a sequence of values; – sequencing means concatenating the output of generators

Note Gnu-C uses the misnomer “statement” instead of command

– … 3

6.1.2

Recursive definitions

15. Three atomic commands in Pascal

Frames: ◊ Expressions are recursively defined ◊ Function call expression constructor ◊ Commands are also recursively defined! ◊ Three atomic commands in Pascal ◊ More on Pascal’s atomic commands ◊ The advent of “expression oriented languages” ◊ Two kinds of atomic commands in C++ ◊ Command expressions in C ◊ More on atomic expressions in C ◊ Two kinds of atomic commands in Java2 ◊ Not all Java expressions make commands

(Ignoring goto, the only sequencer of the language) Empty Can you figure out where it hides?

Pascal

Procedure swap(Var a, b: Integer); Begin a := a + b; b := a - b; a := a - b; end;

12. Expressions are recursively defined

Naturally, each PL is different, but the general scheme is: Atomic expressions

• literals

• variable inspection Expression constructors “-”, …

• Operators such as

Pascal is a separatist language; the semicolon is not part of Assignment the command; hence, an empty command is“+”, hiding here.

As in the above,

Pascal

happy := not happy

• Function call:

Procedure call As in the above,

The set of atomic expressions and the constructors’ set are PL dependent, but the variety is not huge.

Pascal

WriteLn("The Answer!")

13. Function call expression constructor

16. More on Pascal’s atomic commands

Definition 6.2 (Function call expression constructor (dynamic typing version)). If f is a function taking n ≥ 0 arguments, and E1 , . . . , En are expressions, then

Empty no change to state; no computation; no textual representation; existence determined solely by context.

f (E1 , . . . , En )

Assignment

is an expression.

Definition 6.4 (Assignment atomic command). Let v be a variable of type τ , and let E be an expression of type τ , or of compatible type τ 0 , τ 0 ≤ τ . Then,

Only a few cases of type compatibility Pascal, e.g.,

Definition 6.3 (Function call expression constructor INTEGER ≤ REAL, (static typing version)). Let f be a (typed) function of n ≥ 0 in the sense that an integer arguments,

v := E

value could be assigned to a real variable.

(6.1)

is an atomic command.

f ∈ τ1 × · · · × τn → τ .

Let E1 , . . . , En be expressions of types τ1 , . . . , τn . Then, the Procedure call

f (E1 , . . . , En )

Definition 6.5 (Procedure call atomic Command). If p is a procedure taking arguments of types τ1 , . . . , τn , where n ≥ 0 and E1 ∈ τ1 , . . . , En ∈ τn are expressions, then the procedure call

is an expression of type τ . 14. Commands are also recursively defined!

Each PL is different. The scheme is the same, but the variety is huge: Atomic Commands •

p(E1 , . . . , En )

• the empty command

is an atomic command.

…3

• “sequencers”4 Command constructors tor (huge variety)

(6.2)

17. The advent of “expression oriented languages”

• Block command construc-

Pascal sharp distinction between expressions and commands

• Conditional command constructor (huge variety) • Iterative command constructor (huge variety)

• distinction between Function and Procedure

• “try-catch-catch-· · · -finally” command constructor (huge variety)

• distinction between epxression and command

• “With” command constructor (huge variety)

C, Java, Go,… blurred distinction:

• …5

• a procedure is a function returning Unit

2 ignoring

sequencers PL is different 4 WTF? sequencers will be discussed later 5 each PL is different

• an expression is a command, more or less, and subject to PLs variety.

3 each

4

• Not every semicolon makes a command

18. Two kinds of atomic commands in C++

• Not every lonely semicolon makes an empty command

The empty Command does not change the program state; does not perform any computation; textual representation is the semicolon, i.e., “;”

Empty command; no need for loop “body”; all work is carried out by the side-effects of the expression used in the loop condition

• Not every expression followed by a semicolon makes a command

C

while (*s++ = *t++) ;

21. Two kinds of atomic commands in Javaa a ignoring

Just as in C,

Expression marked as Command An atomic command is also “an expression followed by a semicolon”, e.g., In C, assignment is an operator taking two arguments L (left) and R (right). The operator returns R, and as sideeffect, assigns R into L.

sequencers

; the empty command is a lonely semicolon;

C

Expression; provided that the first step in the recursive decomposition of expression is “something” that has (might have) side-effects:

0; 1*1; i; (i=i)==-i; i++ + ++i;

• Function call • Operator with side effects: Assignmnet e.g., =, +=, !sum, add = fn r:real => (n := !n + 1; sum := !sum + r), mean = fn() =>(!sum / real(!n)) } end;

• In discussing type constructors, we introduced the mapping type constructor, e.g., in ML we have the type int->int. • Values of type mapping, can be realized as – Arrays – Functions • It is often the case that functions are not “pure” mappings. – In the imperative paradigm, functions may have side effects – Even in the functional paradigm, functions may depend on values which are not parameters • Do function values behave just like other values?

val makeAccumulator =fn : unit -> {add:real -> unit, count:unit -> int, mean:unit -> real, total:unit -> real} 124. Computing your average grade

• create a new accumulator

ML

val grades = makeAccumulator();

val grades = {add=fn,count=fn,mean=fn,total=fn}: : {add:real -> unit, count:unit -> int, mean:unit -> real, total:unit -> real}

120. Discrimination against function values

In Pascal • Can define variables of almost any type, but not of type function.

• record grade in CS101

ML

(#add grades)(82.0);

• Functions can take function values as parameters, but functions cannot return function values.

val it = () : unit

• record grade in PL ( note that the parenthesis are optional)

121. Function values in C

In C, function values are realized as “function pointers”

ML

#add grades (100.0);

• Can be stored in variables

val it = () : unit

• Can be stored in arrays

• record grade in calculus

• Can be fields of structures

ML

#add grades (37.0);

• Can be passed as parameters

val it = () : unit

• Can be returned from functions

• how many grades so far?

But, C does not allow nested functions.

#count grades ();

122. Nested functions in Gnu-C

val it = 3 : int

Gnu-C is a C dialect, supporting nested functions

Gnu-C

• what’s their total?

int isRightTriangle(double a, double b, double c) { double sqr(double x) { return x * x; } return sqr(a) + sqr(b) == sqr(c); }

#total grades ();

ML ML

val it = 219.0 : real

• what’s my GPA?

• Function sqr is nested in isRightTriangle

#mean grades ();

• Function sqr is inaccessible outside isRightTriangle

val it = 73.0 : real

24

ML

125. The nest is accessible to nested functions

The Gnu-C compiler generates clever code that makes this possible.

Why use nested function?

C

• Nested functions can access variables and definitions of nest

127. Body of function pivot()

• Saves lots of argument passing

int pivot() { // “inherits” // from sort: a, // from qsort: from, to int last = to - 1; int pivot = a[first]; int split = from; swap(split, last); for (int i = first; i < last; i++) if (a[i] < pivot) swap(split++, i); swap(split, last); return split; }

Nesting structure for an implementation of the quick sort algorithm using nested functions: void sort(int a[], int n) { void swap(int i, int j) { }



void qsort(int from, int to) { int pivot() { } } }



128. Using a nested function outside of context



The nested function swap escapes the nest: The Escape



void (*exchange)(int, int);

Figure 6.13: Function nesting structure for an implementation of the quick sort algorithm 126. “Inheritance” of arguments with nested functions

void sort(int a[], int n) { void swap(int i, int j) { // “inherits” (and uses) a // “inherits” (without using) n int t = a[j]; a[i] = a[j]; a[j] = t; } void qsort(int from, int to) { // “inherits” (and uses) a // “inherits” (without using) n int pivot() { // “inherits” and uses argument a // “inherits” (without using) n // also “inherits” (and uses) from, to … } if (from == to) return; int p = pivot(); qsort(from, p); // 1st recursive call qsort(p, to); // 2nd recursive call } qsort(0, n); }

void sort(int a[], int n) { void swap(int i, int j) { … } … exchange = swap; … }

Gnu-C

The escaped value is used in another context: Access to refugee … #define SIZEOF(z) (sizeof(z) / sizeof(z[0]))

Gnu-C

int main(int argc, char **argv) { int a[500]; int b[200]; … sort(b, SIZEOF(b)); … (*exchange)(10,12); … }

Gnu-C

• Would this work? • Does swapping take place in array a or b? Answer: Undefined behavior due to the realization of “activation record” as a machine stack frame.

• At run time, there might be several instances of the recursive function qsort • Function pivot inherits – integers from and to from the correct instance of qsort – integers a from the single instance of sort

129. Function variables & dangling references

Similarly, suppose that Pascal had function variables… 25

132. A stack frame

VAR fv: Integer -> Char; Procedure P; VAR v: … ; Function f(n: Integer): Char; begin …v… end; begin fv := f; end begin P; … fv(0) … end;

int gcd(int m, int n) { if (m == n) return m; int m1 = m; int n1 = n; if (m > n) m1 = m % n; else n1 = n % m; return gcd(m1, n1); }

Java

Pascal

• Each recursive call of gcd – generate a new stack frame

• The environment “dies” as a stack frame is popped.

– push it into the stack

• C forbids nested functions for this reason.

• Each return from a (recursive) call

• Pascal forbids function variable for this reason • To make 1st class “function values”, the activation record cannot be allocated on the hardware stack.

– pop the frame out of the stack – resume computation

[fragile]Understanding the machine stack

R1 , . . . , Rn Saved Registers

int gcd(int m, int n) { if (m == n) return m; int m1 = m; int n1 = n; if (m > n) m1 = m % n; else n1 = n % m; return gcd(m1, n1); }

PC

Java

SP Saved Stack Pointer optional Return Variable m, n Parameters m1, n1 Local Variables m % n, n % m, … Intermediate Results

How does this function“exist” at runtime? Common sequence of bytes, representing machine code

Figure 6.15: Activation record (implemented as stack frame) for function gcd

Per activation the “environment”: • Parameters

133. Activation record

• Local variables

A function call has two components

131. Reminder: CPU & memory in the classical model

Unmapped

• The caller • The callee

Unmapped

Virtual Address Space Code

Heap

Data

Constants

⇒ break

PC ProALU gram Counter Arithmetical Logical Unit R1

R2

···

Rn−1

An activation record represents the interface between the two:

232 − 1

0 Zero

Saved Program Counter

⇐ Stack

• Saved context everything that is required to reconstruct the caller’s state at the end of the call; typically, saved registers.

stack pointer

SP Stack Pointer

• Local state local variables of the callee, intermediate results, etc.

Rn

General Purpose Registers

• Arguments values that the caller sent to the callee

CPU

• Environment variables, functions, definitions, etc. defined by the caller and used by the callee.

Figure 6.14: Reminder: CPU & memory in the classical model

An activation record is often realized by a stack frame. 26

138. The environment: a slightly more precise definition

134. What’s the “environment”?

Definition 6.28 (Environment (first approximation)). Variables, functions, constants, etc., of the caller, which Definition 6.30 (Environment (second approximation)). The set of bindings made in the caller which are available can be used by callee. to the callee. • Does not exist in C/C++ In Pascal, the environment includes • In Pascal, definitions made in a function, are available • The CONST section of the caller (binding of names to to any nested function. values) 135. Acquired bindings in nested functions

• The VAR section of the caller (binding of names to variables)

What’s the environment of pivot?

• The TYPE section of the caller (binding of names to types)

void sort(int a[], int n) { void swap(int i, int j) { …} void qsort(int from, int to) { int pivot() { ???} } … }

Gnu-C

• The LABEL section of the caller (binding of names to labels) • Functions and procedures defined within the caller (binding of names to functions and procedure values)

• Function sort

In C/C++, there is no “caller environment”

• Function swap

139. Environment of a nested function

What’s the environment of function pivot?

• Function qsort • Function pivot

void sort(int a[], int n) { void swap(int i, int j) { …} void qsort(int from, int to) { int pivot() { ??? } } }

Gnu-C

• Arguments to function sort – Array a – Integer n • Arguments to function qsort

Function names in the environment:

– Integer from – Integer to

• The binding of the names: sort, swap, qsort and pivot to the “functions”

136. Name vs. entity

• Binding here is of names to the pointers to functions. Function arguments in the environment:

• But what’s really in the phrase

• Binding of names of arguments to function sort

“variables, functions, constants, etc.”

• Binding of names of arguments to function qsort

• We distinguish between

– These bindings are distinct in each recursive calls.

– Name – Entity

– The semantics of Gnu-C are such that pivot acquires the “correct” bindings.

Note that:

140. Envionment vs. scope

– Entities may have no name (e.g., anonymous functions, classes, allocated variables, etc.) – Entities may have more than one name (e.g., type aliases) – In some cases, a name might have a name, (e.g., tetragrammaton, shemhamphorasch, but also found in reflective programming)

In simple words… • Q: What’s the environment? • A: All variables which are in “scope” • Q: What’s scope? • A: The extent of locations in the program in which a binding is recognized.

137. Binding

Two scoping (binding) rules are found in PLs

Definition 6.29 (Binding). Binding is the tie between a name and an entity

Lexical scoping Bindings not made in function, are determined by where the function is defined.

The phrase “variables, functions, constants, etc.”, means

Synamic scoping Bindings not made in function, are determined by where the function is used.

the set of bindings in the caller available to the callee 27

143. Lexical nesting does not imply call order

141. More on semantics of the environment

When does f2 “inherit” bindings made in f1 ?

void sort(int a[], int n) { void swap(int i, int j) { … } void qsort(int from, int to) { int pivot() { … } } }

Gnu-C

Answer I: (static scoping) If f2 is defined inside f1

Program Code Function f0 {

swap and pivot:

Function f1 {

• Function swap is called by pivot

Function f2 { }

• Function swap is not nested in pivot

}

swap and sort:

}

• Function swap is nested in sort • Function swap is not called by sort

Figure 6.16: Function f2 defined within f1 defined within f0

144. Convoluted calls

• By induction, f2 inherits bindings of f0 if f1 is defined inside f0 .

Who can call function f2 ()?

• Environment defined by static code structure.

Function f0 () { Function f1 () {

(sometimes called static binding, or lexical scoping)

Function f2 () { Function f3 () { f4 () {…}

Answer II: (dynamic scoping) If f2 is called by f1 .

Machine Stack

}

Function f0 { f1 (); }

} }

Function f1 { f2 (); }

Function g1 () { Function g2 () {

Function f2 { … }

Function g3 () {…} }



} }

Figure 6.17: Function f2 called by f1 called by f0 • By induction, f2 inherits bindings of f0 if f1 is called by f0 . • Environment defined by program dynamics (sometimes called dynamic binding)

Figure 6.18: Deep function nesting structure: function fi+1 defined in fi for i = 0, 1, 2, 3; g j+1 defined in gi for j = 1, 2; and, g1 defined in f1 . The caller of f2 is not necessarily f1 ; it could be • function f2 itself

142. Intricacies in static scoping

Definition 6.31 (Static scoping). The environment is determined by scope; if f1 is defined in f2 , then f2 “inherits” bindings made by f1 .

• function f3 defined in f2 • function f4 defined in f3 • …

• There might be more than one activation record of f1 on the stack

• another function g1 defined in f1

• The caller of f2 might not be f1

• function g3 defined in g2

• Static scoping means the most recent version of f1 .

• …

• function g2 defined in g1

But not function f0 within which f1 is defined! 28

148. A simplified static scoping

145. Back pointers in the quick sort example

Consider the following chain of calls: main() → sort() → qsort() → qsort() → qsort() → pivot() → swap()

Frames on the hardware stac

• Then, instead of juggling the BP, one can simply copy the entire set of bindings as arguments.

main

saved state of O/S

swap

>

main

sort

swap



qsort

saved state of pivot void *bp int i int j int t

pivot

pivot saved state of qsort3 void *bp int last int pivot int split int i

of

• Suppose that all bindings in the environment are readonly.

(grows from high memory to low memory, depicted right to left)

Nesting structure

implementation

int argc

qsort3

char **argv

qsort2

qsort1

saved state of qsort2

saved state of qsort1

saved state of sort

void *bp

void *bp

void *bp

saved state of main

int from

int from

int from

int *a

int to

int to

int to

int n

int p

int p

int p

sort

149. Dynamic scoping

int a[500] a[499] a[498]

.. .

Definition 6.32 (Dynamic scoping). The environment is determined by calls; if f1 calls f2 , then f2 “inherits” bindings made by f1 .

a[1] a[0]

int b[200]

Legend

b[199]

Caller’s saved state

Back pointer

Arguments

Local variables

.. .

Dynamic scoping cares not whether there is any relationship between f1 and f2 .

b[0]

• Found in Lisp (but not in Scheme)

Figure 6.19: Back pointers in the quick sort example

• Found in TEX(text processing PL used to make this material)

146. Managing static scoping with back pointers

• The environment is represented as a “back pointer” (BP)

• Found in Perl! • Found in Bash! • Found in HTML/CSS!

• The BP is part of the stack frame • BP points at the stack frame of the most recent version of caller

The de-facto semantics of the C preprocessor. 150. Semantics of dynamic scoping

Using the back pointer: • To access variables defined in f1 function f2 traverses the BP, to find the local state of f1 • To access variables defined in f0 function f2 hop twice through the BP list, to find the local state of f0 • To access variables defined in f−1 (the function within which f0 is defined), make two hops along the BP list. • … 147. Maintaining the back pointer

• Let

void (*exchange)(int, int); void sort(int a[], int n) { void swap(int i, int j) { int t = a[j]; a[i] = a[j]; a[j] = t; } … exchange = swap; … }

Gnu-C

… #define SIZEOF(z) (sizeof(z) / sizeof(z[0]))

F ∈ { f1 , f2 , f3 , . . . , g1 , g2 , g3 , . . .} be a function ready to call f2 .

int main(int argc, char **argv) { int a[500]; int b[500]; … sort(b, SIZEOF(b)); … (*exchange)(10,12); … }

pseudo Gnu-C

• F must traverse the back pointers list to find the “most recent” stack frame of f1 . • Copy this address to the BP of the stack frame of the newly created stack frame for f2 . Number of hops? • If F = f1 , then no hops.

What would work?

• If F = f2 , then one hop.

• sort calling qsort? Yes.

• If F = f3 , then two hops.

• qsort calling qsort? Yes.

• If F = g1 , then one hops.

• qsort calling pivot? Yes.

• If F = g2 , then two hops.

• main calling swap? Yes.

• … 29

151. The runtime bindings dictionary

155. Closures and lifetime

The “binding dictionary”: • Local state is represented by a dictionary • Dictionary supports mapping between names and entities

• Q: what’s the lifetime of a variable enclosed in a closure? • A: the lifetime of the enclosing value.

• Typical entities are variables, constants, and functions.

– In this example, the lifetime of “delta” for each function returned by makeAdder is the lifetime of the return value of makeAdder.

• Typical implementations of dictionary are linked list and hash table.

– The same as lifetime of fields in a record allocated on the heap: live as long as the record is still allocated.

The environment: • The environment is represented as a “back pointer” (BP) to the most recent stack frame. • Thus, we have a “stack of dictionaries”.

In general, you cannot have closures without using GC, rather than the stack for implementation of activation • Search for name is carried out by searching in the stack records. With closures, activation records are allocated of dictionaries. from the heap. • There are means to make this search quite efficient. 156. Closures in ML

152. The environment: a precise definition

Just as in JavaScript, in ML, all functions are closures.

Definition 6.33 (Environment). The environment of a function, is the set of bindings available to this function.

• Standard programming idiom of the language

Environment could be

• Also supports anonymous functions

• Defined statically (static scoping)

• Function values are first class values (including the environment)

• Defined dynamically (dynamic scoping) 153. Closures

6.5.2

• Many modern PLs support closures, where a function can be created in a way that it “keeps with it” the variables that exist in its scope. • Often used in functions-that-return-functions • You can’t do that in Pascal, C, C++ • Very common in functional languages, ML, Python, JavaScript and Java (since version 8.0; uses a hack).

157. Emulation closures with C++ function objects

Class of “adding something” function objects:

class FunctionObjectForAdding { public: FunctionObjectForAdding(int _b): b(_b) {} int operator() (int a) { return a + b; } private: int b; // Saved environment };

A closures factory

# C

function makeAdder(i) { var delta = i; function adder(n) { return n + delta; } return adder; }

• A function object stores a copy of relevant pieces of the environment as data members of the class.

# C

• Environment copy is managed by the function object, which, just like any other C++ variable, can be

var add3 = makeAdder(3); document.write(add3(7)); document.write(add3(12)); var add8 = makeAdder(8) document.write(add8(12));

Output:

Frames: ◊ Emulation closures with C++ function objects ◊ Using C++’s function objects ◊ Closures in Java? ◊ Function objects with Java ◊ An interface for function objects ◊ Another use of the interface for function objects ◊ Using objects of type Function ◊ Functions returning function objects ◊ Using factory functions ◊ Smarter function objects with inner classes ◊ Function objects with inner classes ◊ Inner class of factory function

C++

154. Closures in JavaScript

Usage

Function objects

– present on the stack – allocated from the heap – global

10 15 20

• Memory management is the programmer’s responsibility.

30

Java

158. Using C++’s function objects

class LOG implements Function { // captured environment: final Double logBase; LOG(final Double base) { logBase = Math.log(base); } public Double apply(Double t) { return Math.log(t) / logBase; } }

Usage: #include

C++

int main() { FunctionObjectForAdding add3(3); std::cout >> range

Python

public // sould be pulic to be useful static // factory methods tend to be static Function // Abstract function type mapping(String[] map) { class IntMap // Local class implements Function { public String apply(Integer v) { … // as beforee } } return new IntMap(); }

Java

Python does not make much distinction between functions and generators >>> def fu(n): ... return n ... >>> def countdown(n): ... while n >= 0: ... yield n ... n -= 1 ... >>> fu >>> countdown

Python

Look mom! No hands! Inner class IntMap does not have a map data member! 6.5.3

23:59:50:

Generators

Frames: ◊ A simple Python generator ◊ A generator built on top of another ◊ Functions vs. generators in Python ◊ Use of functions & generators in Python ◊ What’s a generator? ◊ Generators in Icon ◊ Comparions generators ◊ Control with generators ◊ Icon implements control using generators ◊ Generators in C# ◊ Summary of generators 169. A simple Python generator

172. Use of functions & generators in Python

Function fu def fu(x): Python return x

A generator is defined just like a function, except that it uses yield instead of return 33

Use as function:

176. Control with generators

Iteration and conditional are both generting contexts:

>>> fu(3) Python 3

• if statement:

Use as generator

– Execute body if a value is yielded – Only takes on the first first yielded value

>>> for i in fu(3): ... print i ... Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not iterable

Python

• while statement: – Execute body for each value yielded – Uses all yielded values

Generator gen

A simple Icon loop

Pascal

while line := read() do write(line)

def gen(x): Python yield x

A loop with empty body

Use as function:

Python

Pascal

>>> gen(3)

while write(read())

Use as generator

177. Icon implements control using generators

>>> for i in gen(3): ... print i ... 3 >>> exit()

In Icon, all expressions are generators:

Python

Singleton generators 3 is a generator of the sequence {3}. Or generator 3|4|5 quence {3, 4, 5}

173. What’s a generator?

is

a

generator

of

the

se-

Definition 6.34 (Generator). A generator is a function Depth first generation (30|40|50)+(1|2) is a generathat produces a (possibly empty, possibly infinite) sequence tor of the sequence {31, 32, 41, 42} of results, instead of returning a single result. “Product” of sequences (1|2|3)*f() + (1|2) * g() is a generator yielding 6 × n × m where 174. Generators in Icon • n is the number of values that f yields

In Icon, all expressions are generators:

• m is the number of values that f yields

Singleton generators 3 is a generator of the sequence {3}.

178. Generators in C#

Or generator 3|4|5 is a generator of the sequence

In statically typed PLs, generators call for sophisticated Depth first generation (30|40|50)+(1|2) is a genera- typing tor of the sequence {31, 32, 41, 42} “Product” of sequences (1|2|3)*f() + (1|2) * g() is a generator of a sequence with 6 × n × m values, where • n is the number of values that f yields • m is the number of values that f yields 175. Comparions generators

Comparison generators simplify arithmetical conditions • i == j yields { j} if i = j; otherise, the empty sequence {} • i == (3|4|5) succeeds if i ∈ {3, 4, 5}; it yields the value to which i equals. • 0 n if (p.multiply(p).compareTo(n) > 0) break; else if (n.mod(p).compareTo(big(0)) == 0) return false; // Divisor found } // No divisor found return true; }

Java

public static BigInteger nextPrime(BigInteger n) { for (BigInteger $ = succ(n);; $ = succ($)) if (isPrime($)) return $; }

2

208. Maintaining a list of previously found primes for efficiency

2

3

3

5

7

Figure 6.23: Cache of primes (after first insertion) Function extend

Cache.last

Cache.first

Cache.last

Cache.first

static class Cache { … static void extend() { last = last.append( nextPrime(last.prime) ); } }

Java

5

Figure 6.21: Cache of primes (initial state) Cache list item

210. The primes() pseudo generator

static class Node { final BigInteger prime; Node next = null; Node(int p) { this(big(p)); } Node(BigInteger prime) { this.prime = prime; } Node append(BigInteger p) { return next = new Node(p); } Node append(int p) { return append(big(p)); } }

Let’s begin with the trivial, technical parts public static Iterable primes() { return new Iterable() { public Iterator iterator() { return new Iterator() { // There are infinitely many primes: public boolean hasNext() { return true; } // Cannot remove primes public void remove() { throw new UnsupportedOperationException( "remove" ); } … }; } }; }

Java

Java

The cache list static class Cache { static final Node first = new Node(2); static Node last = first.append(3).append(5); static void extend() { last = last.append( nextPrime(last.prime) ); } }

Java

The challenge is in the iterator function next() 211. Function next() in pseudo generator primes()

Iterator function next() must:

209. Extending the cache list

• Retrieve the next prime from the cache • If the cache is exhausted, extend it

Cache.last

Cache.first 2

3

Tricky recursion: • To extend the cache, nextPrime() is called

5

• nextPrime() uses isPrime() • isPrime() iterates over primes()

Figure 6.22: Reminder: initial state of the cache of primes

• But to yield a prime, nextPrime() may need to extend the cache

41

# C

Luckily

void piglet2() { for (;;) { defecate(); if (hungry || thirsty) { suck(); yield sow; } }}

• To yield √ a prime in the order of n, you needs primes until about n. • Cache was initialized with sufficiently primes to get this clockwork going

… return new Iterator() { … // Data member of the inner class Node next = Cache.first; // Yield the next prime from the cache public BigInteger next() { // Save value to be returned final BigInteger $ = next.prime; // Was cache exhausted? if (next == Cache.last) Cache.extend(); // Advance to next node of the cache next = next.next; return $; } };

If piglet2 is not hungry • cow may die

Java

6.5.6

• piglet1 will then die • piglet2 himself will eventually die 214. Issues with the pigsty

It is not clear at all • how the coroutines are started? • how each coroutine gains access to the other? • how can one create multiple instances of the same coroutine? (generate, e.g., several active invocation of piglet2()

Coroutines

Frames: ◊ What are coroutines? ◊ Unconvincing example of coroutines ◊ Issues with the pigsty ◊ Coroutines vs. threads ◊ The sad story of coroutines ◊ Killer application of coroutines ◊ Continuations ◊ Data stored in a continuation ◊ Operations on a continuation ◊ Things you can do with continuations: 212. What are coroutines?

• why coroutines are better than plain threads? So, why the heck do we need these? 215. Coroutines vs. threads

Both offer multi-tasking:

Definition 6.39 (Coroutine). A coroutine is a function, which can

Threads preemptive; execution can be interrupted at any point

• suspend anywhere in its execution by executing a yield command.

Coroutine cooperative; control is Zillions of weird scheduling schemes?

• resume a suspended execution, proceeding to the command that follows the suspending yield

Threads Yes!

Coroutines vs. generators:

Coroutine only with careless programming

• Generators are also called semicoroutines

Race conditions?

• Generator can only yield to its caller

Threads Yes!

• Coroutine typically yield to another coroutine

Coroutine No! (coincidentally, two overloaded meanings of the word “yield” are “to produce” and “to surrender to another the physical Generally speaking, coroutines grant the programmer fine control of something”) control of scheduling, but it may take skill to effectively use this control. 213. Unconvincing example of coroutines A sow and its two little piglets may all die in the pigestry

216. The sad story of coroutines

# C

void sow() { for (;;) { defecate(); if (hungry) feed(); if (thirsty) drink(); yield pigglet1; }}

• invented in the early 60’s (if not earlier) • mostly forgotten; often discarded as “cumbersome multitasking” • have (partial) implementation in mainstream PLs such as C, C++, Java, Python, Perl, Object-Pascal, Smalltalk and more

# C

void piglet1() { for (;;) { defecate(); if (hungry || thirsty) suck(); yield pigglet2; }}

• implementations did not really catch Hence, the poorly designed syntax in the pigsty. 42

217. Killer application of coroutines

220. Operations on a continuation

Event Loops:

c ← start( f (. . .)) create a new continuation for the call f (. . .)

void mainWindow() { for (;;) { Message m = getMessage(); Area a = findScreenArea(a); Windows ws = findWindows(as); push(m); for (Window w: ws) { yield(w); if (!there(m)) break; } } }

# C

c0 ← clone(c) save execution state for later resumable(c) determine whether resumption is possible. c ← resume(c) resume execution of continuation c retrievable(c) determine whether computation has generated a result r ← retrieve(c) obtain the pending returned (yielded) value of c In fact, continuations are nothing but “generation records” with slightly more operations.

# C

void anyWindow() { for (;;) { switch (Message m = getMessage()) { case M1: … case M2: … … default: push(m) } yield mainWindow; } }

221. Things you can do with continuations:

• Good old function calls • Closures • Generators • Exceptions • Coroutines With continuations, you can conceal the fact that Web server should be stateless; (you just provide the client with the server’s continuation record)

Useful in browser applications such Gmail 218. Continuations

Quite an obscure and abstract definition:

6.5.7

Definition 6.40 (Continuation). A continuation is an abstract representation of the control state of a computer program More plainly, a continuation is making the activation record (more generally, the generating record) into a 1st class citizen.

Exercises

1. Which items stored in activation records are not part of the data stored with continuations? 2. How are closures different than anonymous functions? 3. How would you argue that C supports first class functions?

• Invented many years ago

4. What’s non-preemptive multitasking? How is it related to coroutines? Which is more general?

• Has full implementation in many dead and obscure PLs

5. Why is C++ forced to support nested functions?

• Has partial/non-official implementation in many mainstream PLs

6. Enumerate the data items that continuations have to store.

• Did not catch (yet!)

7. What’s the difference between static- and non-static nested classes?

219. Data stored in a continuation

8. What’s the difference between generators and iterators?

Code Where the function is stored in memory, its name, and other meta information, e.g., for debugging.

9. Enumerate all operations allowed on first-class functions.

Environment Activation record, including back-pointers as necessary.

10. Can you use Java’s nested classes to implement anonymous functions?

CPU State The saved registers, most importantly, the PC register

11. Discuss the restrictions placed on nested classes in C++.

Result Last result returned/yielded by the function

12. How are closures different than lambda functions?

Termination status can the continuation be continued

13. What’s the difference, if any, between Java’s local classes, and non-static nested classes? 43

14. Discuss the restrictions placed on anonymous functions in Gnu-C.

41. Can coroutines be implemented with closures? Explain.

15. Given is a language which only has generators, can you use these to implement coroutines?

42. Explain why letting the called function to remove the arguments from the stack is more efficient than having the caller do so.

16. What’s the etymology of the name “lambda” functions?

43. What’s the difference between coroutines and generators?

17. How are C++ nested classes different than those of Java?

44. Does Java make distinction between generators and iterators? How?

18. Why do continuations require GC? 19. Why does Pascal refuse to give equal rights to functions? 20. Can closures be implemented with activation records? Explain. 21. What are the two meanings of the word “yield”? How are these meaning used in generators and 22. Which stored in activation records are not part of the data stored with closures? 23. Explain why C does not have nested functions. 24. Are data items stored with activation records different in C and in Pascal? 25. Enumerate the data items stored in an activation record? 26. Are nested functions in C++ first class? 27. Enumerate the data items that closures have to store. 28. Can you use Java’s nested classes to implement closures? 29. When are closures planned for Java? What’s the proposed syntax? Any restrictions on the implementation? 30. Why do closures require GC? 31. Which data items stored with closures do not occur in activation records? 32. How does Java implement generators? 33. What information is contained in coroutines and is missing in closures? 34. When are closures planned for C++? What’s the proposed syntax? Any restrictions on the implementation? 35. Can one emulate closures with coroutines? Explain. 36. Are goroutines a kind of coroutines? 37. In C the calling function is responsible for removing the pushed arguments from the stack. Why is this the only reasonable implementation? 38. Describe the typical situation in which you want your closure to be anonymous? 39. Can you use Java’s nested classes to implement coroutines? If yes, explain how; if no, explain why not. 40. Experts claim that all “implementation of all web services are poor-man’s continuations”. Explain and elaborate. 44