# Conference: Week 2

#### Table Of Contents

### Lecture Material

- Grammers, Derivations, Parse Trees.
- \(\lambda\) calculus, Evaluation Rule, Renaming, Confluence.

### Function vs. Imperative Programming

- Pros?
- Cons?
- Which is Better?

### MapReduce

**The original paper:**Jeffrey Dean and Sanjay Ghemawat, MapReduce: Simplified Data Processing on Large Clusters, OSDI ’04: Sixth Symposium on Operating System Design and Implementation, San Francisco, CA, December, 2004.

### Lambda Calculus Basics

Consider the following \(\lambda\)-calculus expression \(M\):

`M = (λy.y + y)((λx.x + x) 3)`

Reduce \(M\) in two different ways:

- Always evaluate the right-most reducible \(\lambda\) term.
- Always evaluate the left-most reducible \(\lambda\) term.

Which corresponds to the way in which you imagine most programming languages evaluate function calls and the parameters passed to them?

Which reduction is longer? Can you construct another term \(M'\) so that the opposite strategy yields the longer reducton? It need not compute the same value as \(M\). One way to approach this is to think abut how you could change \(M\) to achieve the effect you want.

SolutionRight-most:

`M = (λy.y + y)((λx.x + x) 3) = (λy.y + y)(3 + 3) = (λy.y + y)(6) = 6 + 6 = 12`

Left-most:

`M = (λy.y + y)((λx.x + x) 3) = ((λx.x + x) 3) + ((λx.x + x) 3) = (3 + 3) + ((λx.x + x) 3) = 6 + ((λx.x + x) 3) = 6 + (3 + 3) = 6 + 6 = 12`

The right-most strategy corresponds to most languages. It reflects an

*eager*evaluation strategy in which you evaluate the arguments to a function before beginning to run the code for the function. Left-most is akin to*lazy*evaluation, which we’ll explore shortly.Right-most required 2, Left-most required 3. However, that is not always the case. Consider:

`M' = (λy.0)((λx.x + x) 3)`

Right-most requires 2 steps, but left-most requires only 1, since the parameter value is not used.

### Lambda Calculus Homework Questions

All good?

### [Extra] Church Numerals and Arithmetic

I said in lecture that variables, function definition, and function application are sufficient to capture the essence of every programming language. While we often use them for convenience, not even numbers and math operations are unnecessary. The next two questions illustrates that by showing how to encode arithmetic and recursion using only the 3 core \(\lambda\) calculus features. Any other feature of a programming language can be similarly encoded.

Church numerals are an encoding of Natural numbers in \(\lambda\) calculus. The first few numbers are defined as follows:

```
0 := λf.λx.x
1 := λf.λx.f x
2 := λf.λx.f (f x)
3 := λf.λx.f (f (f x))
4 := λf.λx.f (f (f (f x)))
```

We can also encode basic math operations using only function definition, application, and variables. For example:

```
PLUS := λm.λn.λf.λx.m f (n f x)
MULT := λm.λn.λf.m (n f)
```

Demonstrate how this works by showing that `1 + 2 == 3`

:

```
(PLUS 1) 2
= ((λm.λn.λf.λx. (m f)(n f x)) (λf.λx.f x)) (λf.λx.f (f x))
= ...
= λf.λx.f (f (f x))
= 3
```

```
(PLUS 1) 2
= ((λm.λn.λf.λx.(m f) (n f x)) (λf.λx.f x)) (λf.λx.f (f x))
= ((λm.λn.λf.λx.(m f) (n f x)) (λf'.λx'.f' x')) (λf''.λx''.f'' (f'' x''))
= (λn.λf.λx.((λf'.λx'.f' x') f) (n f x)) (λf''.λx''.f'' (f'' x''))
= (λn.λf.λx.(λx'.f x') (n f x)) (λf''.λx''.f'' (f'' x''))
= (λn.λf.λx.f (n f x)) (λf''.λx''.f'' (f'' x''))
= (λf.λx.f ((λf''.λx''.f'' (f'' x'')) f x))
= (λf.λx.f ((λx''.f (f x'')) x))
= (λf.λx.f (f (f x))
= 3
```

### [Extra] The Y Combinator

We can also write recursive functions in \(\lambda\)-calculus, although doing so requires a little additional work and the *Y combinator*:

`Y := λg.(λx.g (x x)) (λx.g (x x))`

(Yes, the start-up incubator Y Combinator is named after this \(\lambda\) term. That company was founded by some of those involved in ViaWeb/Yahoo StoreFront from a couple lectures ago…)

The Y combinator has a key property that enables us to produce recursive computation. Specifically, for some term `g`

:

```
Y g = (λh.(λx.h (x x)) (λx.h (x x))) g
= (λx.g (x x)) (λx.g (x x))
= g ((λx.g (x x)) (λx.g (x x)))
= g (Y g)
= g (g (Y g))
= g (g (g (Y g)))
= ...
```

Now suppose G is

`G := λr. λn.(if n = 1 then 1 else n × (r (n−1)))`

Show that `(Y G) 3`

computes \(3!\):

```
(Y G) 3 = (G (Y G)) 3
= ((λr.λn.(if n = 1 then 1 else n × (r (n−1)))) (Y G)) 3
= ...
= 3 × (2 × 1)
= 6
```

```
(Y G) 3
= (G (Y G)) 3
= ((λr.λn.(if n = 1 then 1 else n × (r (n−1)))) (Y G)) 3
= (λn.(if n = 1 then 1 else n × ((Y G) (n−1)))) 3
= if 3 = 1 then 1 else 3 × ((Y G) 2)
= 3 × ((Y G) 2)
= 3 × ((G (Y G)) 2)
= 3 × (((λr.λn.(if n = 1 then 1 else n × (r (n−1)))) (Y G)) 2)
= 3 × ((λn.(if n = 1 then 1 else n × ((Y G) (n−1)))) 2)
= 3 × (if 2 = 1 then 1 else 2 × ((Y G) 1))
= 3 × (2 × ((Y G) 1))
= 3 × (2 × ((G (Y G)) 1))
= 3 × (2 × (((λr.λn.(if n = 1 then 1 else n × (r (n−1)))) (Y G)) 1))
= 3 × (2 × ((λn.(if n = 1 then 1 else n × ((Y G) (n−1)))) 1))
= 3 × (2 × (if 1 = 1 then 1 else 1 × ((Y G) 0)))
= 3 × (2 × 1)
= 6
```