Fundamentals and lambda calculus Deian Stefan (adopted from my - - PowerPoint PPT Presentation

fundamentals and lambda calculus
SMART_READER_LITE
LIVE PREVIEW

Fundamentals and lambda calculus Deian Stefan (adopted from my - - PowerPoint PPT Presentation

Fundamentals and lambda calculus Deian Stefan (adopted from my & Edward Yangs CSE242 slides) Logistics Assignments: Programming assignment 1 is out Homework 1 will be released tomorrow night Podcasting: everything should be


slide-1
SLIDE 1

Fundamentals and lambda calculus

Deian Stefan (adopted from my & Edward Yang’s CSE242 slides)

slide-2
SLIDE 2

Logistics

  • Assignments:

➤ Programming assignment 1 is out ➤ Homework 1 will be released tomorrow night

  • Podcasting: everything should be set
  • Section: 8-8:50AM default; TA choice to do 3-3:50PM
  • Clickers, sign up: see piazza/course page for link

➤ We’ll use them today

slide-3
SLIDE 3

JavaScript functions

  • JavaScript functions are first-class

➤ Syntax is a bit ugly/terse when you want to use

functions as values; recall block scoping:
 
 (function () {
 // ... do something
 }) ();

  • New version has cleaner syntax called “fat arrows”

➤ Semantics not always the same (this has different

meaning), but for this class should always be safe to use

slide-4
SLIDE 4

fat-arrows.js

slide-5
SLIDE 5

In this lecture

slide-6
SLIDE 6

In this lecture

slide-7
SLIDE 7

In this lecture

slide-8
SLIDE 8

In this lecture

λ

slide-9
SLIDE 9

What is the lambda calculus?

  • Simplest reasonable programming language

➤ Only has one feature: functions

slide-10
SLIDE 10

Why study it?

  • Captures the idea of first-class functions

➤ Good system for studying the concept of variable

binding that appears in almost all languages

  • Historically important

➤ Competing model of computation introduced by

Church as an alternative to Turing machines:
 substitution (you’ll see this today) = symbolic comp

➤ Influenced Lisp (thus JS), ML, Haskell, C++, etc.

slide-11
SLIDE 11

Why else?

  • Base for studying many programming languages

➤ You can use lambda calculus and extended it in

different ways to study languages and features

➤ E.g., we can study the difference between strict

languages like JavaScript and lazy ones like Haskell

➤ λ + evaluation strategy ➤ E.g., we can study different kinds of type systems ➤ Simply-typed λ calculus, polymorphic, etc.

slide-12
SLIDE 12
  • Most PL papers describe language models that build
  • n lambda calculus

➤ Understanding λ will help you interpret what you are

reading in PL research papers

➤ Understanding λ will help you get started with other

formal/theoretical foundations:

➤ Operational semantics ➤ Denotational semantics

Why else?

slide-13
SLIDE 13

Before we get started, some terminology

  • Syntax (grammar)

➤ The symbols used to write a program ➤ E.g., (x + y) is a grammatical expression

  • Semantics

➤ The actions that occur when a program is executed

  • PL implementation: Syntax -> Semantics
slide-14
SLIDE 14

Before we get started, some terminology

  • Syntax (grammar)

➤ The symbols used to write a program ➤ E.g., (x + y) is a grammatical expression

  • Semantics

➤ The actions that occur when a program is executed

  • PL implementation: Syntax -> Semantics
slide-15
SLIDE 15

Before we get started, some terminology

  • Syntax (grammar)

➤ The symbols used to write a program ➤ E.g., (x + y) is a grammatical expression

  • Semantics

➤ The actions that occur when a program is executed

  • PL implementation: Syntax -> Semantics
slide-16
SLIDE 16

Today

  • Syntax of λ calculus
  • Semantics of λ calculus

➤ Free and bound variables ➤ Substitution ➤ Evaluation order

slide-17
SLIDE 17

Lambda calculus

  • Language syntax (grammar):

➤ Expressions: e ::= x | λx.e | e1 e2

➤ Variables: x ➤ Functions or λ abstractions: λx.e ➤ This is the same as x => e in JavaScript! ➤ Function application: e1 e2 ➤ This is the same as e1 (e2) in JavaScript!

slide-18
SLIDE 18

Example terms

➤ λx.(2+x) ➤ Same as: x => (2 + x) ➤ (λx.(2 + x)) 5 ➤ Same as: (x => (2 + x)) (5) ➤ (λf.(f 3)) (λx.(x + 1)) ➤ Same as: (f => (f (3))) (x => (x+1))

slide-19
SLIDE 19

Example terms

➤ λx.(2+x) ➤ Same as: x => (2 + x) ➤ (λx.(2 + x)) 5 ➤ Same as: (x => (2 + x)) (5) ➤ (λf.(f 3)) (λx.(x + 1)) ➤ Same as: (f => (f (3))) (x => (x+1))

LIES! What is this “2” and “+”? (Sugar.)

slide-20
SLIDE 20

Example terms

➤ λx.(2+x) ➤ Same as: x => (2 + x) ➤ (λx.(2 + x)) 5 ➤ Same as: (x => (2 + x)) (5) ➤ (λf.(f 3)) (λx.(x + 1)) ➤ Same as: (f => (f (3))) (x => (x+1))

slide-21
SLIDE 21

Example terms

➤ λx.(2+x) ➤ Same as: x => (2 + x) ➤ (λx.(2 + x)) 5 ➤ Same as: (x => (2 + x)) (5) ➤ (λf.(f 3)) (λx.(x + 1)) ➤ Same as: (f => (f (3))) (x => (x+1))

slide-22
SLIDE 22

Example terms

➤ λx.(2+x) ➤ Same as: x => (2 + x) ➤ (λx.(2 + x)) 5 ➤ Same as: (x => (2 + x)) (5) ➤ (λf.(f 3)) (λx.(x + 1)) ➤ Same as: (f => (f (3))) (x => (x+1))

slide-23
SLIDE 23

JavaScript to λ calculus

  • Let’s look at function composition: (f◦f)(x)
  • In JavaScript:

➤ f => (x => f (f (x))) ➤ ((f => (x => f (f (x)))) (x => x+1)) (4)

  • In λ:

➤ λf.(λx. f (f x)) ➤ ((λf.(λx. f (f x)) (λx.x+1)) 4

slide-24
SLIDE 24

JavaScript to λ calculus

  • Let’s look at function composition: (f◦f)(x)
  • In JavaScript:

➤ f => (x => f (f (x))) ➤ ((f => (x => f (f (x)))) (x => x+1)) (4)

  • In λ:

➤ λf.(λx. f (f x)) ➤ ((λf.(λx. f (f x)) (λx.x+1)) 4

slide-25
SLIDE 25

JavaScript to λ calculus

  • Let’s look at function composition: (f◦f)(x)
  • In JavaScript:

➤ f => (x => f (f (x))) ➤ ((f => (x => f (f (x)))) (x => x+1)) (4)

  • In λ:

➤ λf.(λx. f (f x)) ➤ ((λf.(λx. f (f x)) (λx.x+1)) 4

slide-26
SLIDE 26

Today

  • Syntax of λ calculus ✓
  • Semantics of λ calculus

➤ Free and bound variables ➤ Substitution ➤ Evaluation order

slide-27
SLIDE 27

Semantics of λ calculus

  • Reduce a term to another as much as we can

➤ If we can’t reduce it any further, the term is said to

be in normal form

  • How? Rewrite terms!
slide-28
SLIDE 28

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-29
SLIDE 29

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-30
SLIDE 30

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-31
SLIDE 31

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-32
SLIDE 32

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-33
SLIDE 33

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-34
SLIDE 34

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-35
SLIDE 35

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-36
SLIDE 36

Example terms

  • Example: (λx.(2 + x)) 5 → (2 + 5) → 7

➤ In JavaScript: (x => (2 + x)) (5) → (2 + 5) → 7

  • Example: (λf.(f 3)) (λx.(x + 1))


→ ((λx.(x + 1)) 3)
 → (3 + 1) → 4

➤ In JavaScript: (f => (f (3))) (x => (x+1))


→ ((x => (x+1)) (3)
 → (3+1) → 4

slide-37
SLIDE 37

Easy! Pattern: for function application substitute the term you are applying the function to for the argument variable

slide-38
SLIDE 38

Substitution (not right)

  • Substitution: e1 [x := e2]

➤ Replace every occurrence of x in e1 with e2

  • General reduction rule for λ calculus:

➤ (λx.e1) e2 → e1 [x := e2] ➤ Function application rewritten to


e1 (the function body) with every x in e1
 substituted with e2 (argument)

slide-39
SLIDE 39

A more complicated example

slide-40
SLIDE 40

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4

slide-41
SLIDE 41

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4 ➤ (λx. (λx.x+1) ((λx.x+1) x)) 4

slide-42
SLIDE 42

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4 ➤ (λx. (λx.x+1) ((λx.x+1) x)) 4 ➤ (λx.x+1) ((λx.x+1) 4)

slide-43
SLIDE 43

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4 ➤ (λx. (λx.x+1) ((λx.x+1) x)) 4 ➤ (λx.x+1) ((λx.x+1) 4) ➤ (λx.x+1) (4+1)

slide-44
SLIDE 44

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4 ➤ (λx. (λx.x+1) ((λx.x+1) x)) 4 ➤ (λx.x+1) ((λx.x+1) 4) ➤ (λx.x+1) (4+1) ➤ 4+1+1

slide-45
SLIDE 45

A more complicated example

  • Compose function that adds 1 to arg & apply it to 4

➤ ((λf.(λx. f (f x)) (λx.x+1)) 4 ➤ (λx. (λx.x+1) ((λx.x+1) x)) 4 ➤ (λx.x+1) ((λx.x+1) 4) ➤ (λx.x+1) (4+1) ➤ 4+1+1 ➤ 6

slide-46
SLIDE 46

Let’s make this even more fun!

slide-47
SLIDE 47

Let’s make this even more fun!

  • Instead of 1, let’s add x to argument (& do it 2 times):

➤ (λf.(λx. f (f x)) (λy.y+x)

slide-48
SLIDE 48

Let’s make this even more fun!

  • Instead of 1, let’s add x to argument (& do it 2 times):

➤ (λf.(λx. f (f x)) (λy.y+x) ➤ λx. (λy.y+x) ((λy.y+x) x)

slide-49
SLIDE 49

Let’s make this even more fun!

  • Instead of 1, let’s add x to argument (& do it 2 times):

➤ (λf.(λx. f (f x)) (λy.y+x) ➤ λx. (λy.y+x) ((λy.y+x) x) ➤ λx. (λy.y+x) (x+x)

slide-50
SLIDE 50

Let’s make this even more fun!

  • Instead of 1, let’s add x to argument (& do it 2 times):

➤ (λf.(λx. f (f x)) (λy.y+x) ➤ λx. (λy.y+x) ((λy.y+x) x) ➤ λx. (λy.y+x) (x+x) ➤ λx. (x+x+x)

slide-51
SLIDE 51

Let’s make this even more fun!

  • Instead of 1, let’s add x to argument (& do it 2 times):

➤ (λf.(λx. f (f x)) (λy.y+x) ➤ λx. (λy.y+x) ((λy.y+x) x) ➤ λx. (λy.y+x) (x+x) ➤ λx. (x+x+x)

????
 that’s not a function that adds
 x to argument two times

slide-52
SLIDE 52

Substitution is surprisingly complex

  • Recall our reduction rule for application:

➤ (λx.e1) e2 → e1 [x := e2] ➤ This function application reduces to 


e1 (the function body) where every x in e1 
 is substituted with e2 (value we’re applying func to)

➤ Where did we go wrong? When we substituted: ➤ (λf.(λx. f (f x)) (λy.y+x) ➤ (λx. (λy.y+x) ((λy.y+x) x) the x is captured!

slide-53
SLIDE 53

Another way to see the problem

  • Syntactic sugar: let x = e1 in e2 ≝ (λx.e2) e1
  • Let syntax makes this easy to see:

➤ let x = a+b in let x = a+b in


let a = 7 in → let a = 7 in
 x + a (a+b) + a

➤ Very obviously wrong! ➤ But, guess what: your C macro preprocessor does this!

slide-54
SLIDE 54

Another way to see the problem

  • Syntactic sugar: let x = e1 in e2 ≝ (λx.e2) e1
  • Let syntax makes this easy to see:

➤ let x = a+b in let x = a+b in


let a = 7 in → let a = 7 in
 x + a (a+b) + a

➤ Very obviously wrong! ➤ But, guess what: your C macro preprocessor does this!

slide-55
SLIDE 55

Fixing the problem

  • How can we fix this?

1.Rename variables!

➤ let x = a+b in let x = a+b in let x = a+b in 


let a = 7 in → let a123 = 7 in → let a123 = 7 in
 x + a x + a123 (a+b) + a123 2.Do the “dumb” substitution!

slide-56
SLIDE 56

Fixing the problem

  • How can we fix this?

1.Rename variables!

➤ let x = a+b in let x = a+b in let x = a+b in 


let a = 7 in → let a123 = 7 in → let a123 = 7 in
 x + a x + a123 (a+b) + a123 2.Do the “dumb” substitution!

slide-57
SLIDE 57

Fixing the problem

  • How can we fix this?

1.Rename variables!

➤ let x = a+b in let x = a+b in let x = a+b in 


let a = 7 in → let a123 = 7 in → let a123 = 7 in
 x + a x + a123 (a+b) + a123 2.Do the “dumb” substitution!

slide-58
SLIDE 58

Why is this the way to go?

  • We can always rename bound variables!

➤ Def: variable x is bound in λx.(x+y)

  • Bound variables are just “placeholders”

➤ Above: x is not special, we could have used z ➤ We say they are equivalent: λx.(x+y) =𝝱 λz.(z+y)

  • Renaming amounts to converting bound variable

names to avoid capture: e.g., λx.(x+y) to λz.(z+y)

slide-59
SLIDE 59

Can we rename everything?

  • Can we rename y in λx.(x+y)? (A: yes, B: no)

➤ No! We don’t know what y may be, so we must keep

it as is!

  • Intuition:

➤ Can change the name of your function argument

variables but not of variables from the outer scope

➤ E.g., ∀x. P(x, y) or ∑i∈{1,…,10} xi + y

slide-60
SLIDE 60

Can we rename everything?

  • Can we rename y in λx.(x+y)? (A: yes, B: no)

➤ No! We don’t know what y may be, so we must keep

it as is!

  • Intuition:

➤ Can change the name of your function argument

variables but not of variables from the outer scope

➤ E.g., ∀x. P(x, y) or ∑i∈{1,…,10} xi + y

slide-61
SLIDE 61

Can we rename everything?

  • Can we rename y in λx.(x+y)? (A: yes, B: no)

➤ No! We don’t know what y may be, so we must keep

it as is!

  • Intuition:

➤ Can change the name of your function argument

variables but not of variables from the outer scope

➤ E.g., ∀x. P(x, y) or ∑i∈{1,…,10} xi + y

slide-62
SLIDE 62

Let’s think about this more formally

slide-63
SLIDE 63

Def: free variables

  • If a variable is not bound by a λ, we say that it is free

➤ e.g., y is free in λx.(x+y) ➤ is x free? No! We say x is bound in λx.(x+y)

  • We can compute the free variables of any term:

➤ FV(x) = {x} ➤ FV(λx.e) = FV(e) \ {x} ➤ FV(e1 e2) = FV(e1) ∪ FV(e2)

slide-64
SLIDE 64

Def: free variables

  • If a variable is not bound by a λ, we say that it is free

➤ e.g., y is free in λx.(x+y) ➤ is x free? No! We say x is bound in λx.(x+y)

  • We can compute the free variables of any term:

➤ FV(x) = {x} ➤ FV(λx.e) = FV(e) \ {x} ➤ FV(e1 e2) = FV(e1) ∪ FV(e2)

slide-65
SLIDE 65

Def: free variables

  • If a variable is not bound by a λ, we say that it is free

➤ e.g., y is free in λx.(x+y) ➤ is x free? No! We say x is bound in λx.(x+y)

  • We can compute the free variables of any term:

➤ FV(x) = {x} ➤ FV(λx.e) = FV(e) \ {x} ➤ FV(e1 e2) = FV(e1) ∪ FV(e2)

slide-66
SLIDE 66

Def: free variables

  • If a variable is not bound by a λ, we say that it is free

➤ e.g., y is free in λx.(x+y) ➤ is x free? No! We say x is bound in λx.(x+y)

  • We can compute the free variables of any term:

➤ FV(x) = {x} ➤ FV(λx.e) = FV(e) \ {x} ➤ FV(e1 e2) = FV(e1) ∪ FV(e2)

slide-67
SLIDE 67

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-68
SLIDE 68

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-69
SLIDE 69

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-70
SLIDE 70

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-71
SLIDE 71

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-72
SLIDE 72

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-73
SLIDE 73

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-74
SLIDE 74

Def: Capture-avoiding substitution

  • Capture-avoiding substitution:

➤ x[x:=e] = e ➤ y[x:=e] = y if y ≠ x ➤ (e1 e2)[x := e] = (e1[x := e]) (e2[ x:= e]) ➤ (λx.e1)[x := e] = λx.e1 ➤ (λy.e1)[x := e2] = λy.e1[x := e2] if y ≠ x and y ∉ FV(e2) ➤ Why the if? If y is free in e2 this would capture it!

slide-75
SLIDE 75

Lambda calculus: equational theory

  • α-renaming or α-conversion

➤ λx.e = λy.e[x:=y] where y∉FV(e)

  • β-reduction

➤ (λx.e1) e2 = e1 [x:=e2]

  • η-conversion

➤ λx.(e x) = e where x∉FV(e)

  • We define our → relation using these equations!
slide-76
SLIDE 76

Back to our example (what we should’ve done)

slide-77
SLIDE 77

Back to our example (what we should’ve done)

  • Instead of 1, let’s add x to argument (and do it 2x):

➤ (λf.(λx. f (f x)) (λy.y+x)

slide-78
SLIDE 78

Back to our example (what we should’ve done)

  • Instead of 1, let’s add x to argument (and do it 2x):

➤ (λf.(λx. f (f x)) (λy.y+x) =α (λf.(λz. f (f z)) (λy.y+x)

slide-79
SLIDE 79

Back to our example (what we should’ve done)

  • Instead of 1, let’s add x to argument (and do it 2x):

➤ (λf.(λx. f (f x)) (λy.y+x) =α (λf.(λz. f (f z)) (λy.y+x) =β λz. (λy.y+x) ((λy.y+x) z)

slide-80
SLIDE 80

Back to our example (what we should’ve done)

  • Instead of 1, let’s add x to argument (and do it 2x):

➤ (λf.(λx. f (f x)) (λy.y+x) =α (λf.(λz. f (f z)) (λy.y+x) =β λz. (λy.y+x) ((λy.y+x) z) =β λz. (λy.y+x) (z+x)

slide-81
SLIDE 81

Back to our example (what we should’ve done)

  • Instead of 1, let’s add x to argument (and do it 2x):

➤ (λf.(λx. f (f x)) (λy.y+x) =α (λf.(λz. f (f z)) (λy.y+x) =β λz. (λy.y+x) ((λy.y+x) z) =β λz. (λy.y+x) (z+x) =β λz. z+x+x

slide-82
SLIDE 82

Today

  • Syntax of λ calculus ✓
  • Semantics of λ calculus ✓

➤ Free and bound variables ✓ ➤ Substitution ✓ ➤ Evaluation order

slide-83
SLIDE 83

Evaluation order

  • What should we reduce first in (λx.x) ((λy.y) z)?

➤ A: The outer term: (λy.y) z ➤ B: The inner term: (λx.x) z

  • Does it matter?

➤ No! They both reduce to z! ➤ Church-Rosser Theorem: “If you reduce to a normal

form, it doesn’t matter what order you do the reductions.” This is known as confluence.

slide-84
SLIDE 84

Evaluation order

  • What should we reduce first in (λx.x) ((λy.y) z)?

➤ A: The outer term: (λy.y) z ➤ B: The inner term: (λx.x) z

  • Does it matter?

➤ No! They both reduce to z! ➤ Church-Rosser Theorem: “If you reduce to a normal

form, it doesn’t matter what order you do the reductions.” This is known as confluence.

slide-85
SLIDE 85

Evaluation order

  • What should we reduce first in (λx.x) ((λy.y) z)?

➤ A: The outer term: (λy.y) z ➤ B: The inner term: (λx.x) z

  • Does it matter?

➤ No! They both reduce to z! ➤ Church-Rosser Theorem: “If you reduce to a normal

form, it doesn’t matter what order you do the reductions.” This is known as confluence.

slide-86
SLIDE 86

Does evaluation order really not matter?

slide-87
SLIDE 87

Does evaluation order really not matter?

  • Consider a curious term called Ω

➤ Ω ≝ (λx.x x) (λx.x x)

slide-88
SLIDE 88

Does evaluation order really not matter?

  • Consider a curious term called Ω

➤ Ω ≝ (λx.x x) (λx.x x) =β (x x)[ x:= (λx.x x)]

slide-89
SLIDE 89

Does evaluation order really not matter?

  • Consider a curious term called Ω

➤ Ω ≝ (λx.x x) (λx.x x) =β (x x)[ x:= (λx.x x)] =β (λx.x x) (λx.x x)

slide-90
SLIDE 90

Does evaluation order really not matter?

  • Consider a curious term called Ω

➤ Ω ≝ (λx.x x) (λx.x x) =β (x x)[ x:= (λx.x x)] =β (λx.x x) (λx.x x) = Ω Deja vu!

slide-91
SLIDE 91

(Ω has no normal form)

Ω →Ω →Ω →Ω →Ω →Ω →Ω

slide-92
SLIDE 92

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω

slide-93
SLIDE 93

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω y

slide-94
SLIDE 94

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω y (λx.y) Ω

slide-95
SLIDE 95

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω y y (λx.y) Ω

slide-96
SLIDE 96

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω y y (λx.y) Ω (λx.y) Ω

slide-97
SLIDE 97

Does evaluation order really not matter?

  • Consider a function that ignores its argument: (λx.y)
  • What happens when we call it on Ω?



 
 (λx.y) Ω y y (λx.y) Ω (λx.y) Ω y (λx.y) Ω y

slide-98
SLIDE 98

Does evaluation order really not matter?

  • Nope! Evaluation order does matter!
slide-99
SLIDE 99

Call-by-value

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 →…→ (λx.e1’) n → e1’[x:=n]

  • JavaScript’s evaluation strategy is call-by-value (ish)

➤ What does this program do? ➤ (x => 33) ((x => x(x)) (x => x(x))) ➤ RangeError: Maximum call stack size exceeded

slide-100
SLIDE 100

Call-by-value

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 →…→ (λx.e1’) n → e1’[x:=n]

  • JavaScript’s evaluation strategy is call-by-value (ish)

➤ What does this program do? ➤ (x => 33) ((x => x(x)) (x => x(x))) ➤ RangeError: Maximum call stack size exceeded

slide-101
SLIDE 101

Call-by-value

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 →…→ (λx.e1’) n → e1’[x:=n]

  • JavaScript’s evaluation strategy is call-by-value (ish)

➤ What does this program do? ➤ (x => 33) ((x => x(x)) (x => x(x))) ➤ RangeError: Maximum call stack size exceeded

slide-102
SLIDE 102

Call-by-value

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 →…→ (λx.e1’) n → e1’[x:=n]

  • JavaScript’s evaluation strategy is call-by-value (ish)

➤ What does this program do? ➤ (x => 33) ((x => x(x)) (x => x(x))) ➤ RangeError: Maximum call stack size exceeded

slide-103
SLIDE 103

Call-by-value

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 →…→ (λx.e1’) n → e1’[x:=n]

  • JavaScript’s evaluation strategy is call-by-value (ish)

➤ What does this program do? ➤ (x => 33) ((x => x(x)) (x => x(x))) ➤ RangeError: Maximum call stack size exceeded

slide-104
SLIDE 104

Call-by-name

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 → e1’[x:=e2] →…

  • Haskell’s evaluation strategy is call-by-name

➤ It only does what is absolutely necessary!

slide-105
SLIDE 105

Call-by-name

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 → e1’[x:=e2] →…

  • Haskell’s evaluation strategy is call-by-name

➤ It only does what is absolutely necessary!

slide-106
SLIDE 106

Call-by-name

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 → e1’[x:=e2] →…

  • Haskell’s evaluation strategy is call-by-name

➤ It only does what is absolutely necessary!

slide-107
SLIDE 107

Call-by-name

  • Reduce function, then reduce args, then apply

➤ e1 e2 →…→ (λx.e1’) e2 → e1’[x:=e2] →…

  • Haskell’s evaluation strategy is call-by-name

➤ It only does what is absolutely necessary!

slide-108
SLIDE 108

Summary

  • A term may have many redexes (subterms can reduce)

➤ Evaluation strategy says which redex to evaluate ➤ Evaluation not guaranteed to find normal form

  • Call-by-value: evaluate function & args before β reduce
  • Call-by-name: evaluate function, then β-reduce
slide-109
SLIDE 109

Today

  • Syntax of λ calculus ✓
  • Semantics of λ calculus ✓

➤ Free and bound variables ✓ ➤ Substitution ✓ ➤ Evaluation order ✓

slide-110
SLIDE 110

Takeaway

  • λ-calculus is a forma system

➤ “Simplest reasonable programming language”-Ramsey ➤ Binders show up everywhere! ➤ Know your capture-avoiding substitution!