# Environments - Fri, Sep 6

## Environments for Higher-Order Functions

**Functions are first-class**: in Python, they are values just as numbers**Higher-order functions**: functions that take functions as arguments or return functions as return values

```
def square(x): # func square(x) [parent=Global]
return x * x
def apply_twice(f, x): # func apply_twice(f, x) [parent=Global]
return f(f(x))
```

## Applying a user-defined function

- Create a new frame
- Bind formal parameters to arguments
- Execute the body:
`return f(f(x))`

## Environments for Nested Definitions

```
def make_adder(n): # func make_adder(n) [parent=Global]
def adder(k): # func adder(k) [parent=f1]
return n + k
return adder
```

Note that `adder`

has no parent until `make_adder`

is run.

- When the frame
`f1: make_adder [parent=Global]`

is created, a new `func adder(k)`

is created with `[parent=f1]`

. - This function is evaluated in its own frame
`f2: adder [parent=f1]`

.

## How to Draw an Environment Diagram

When a function is called:

- Create a function value
`func <name>(<formal parameters>) [parent=<label>]`

- Its parent is the current frame
- Bind
`<name>`

to the function value in the current frame

## Local Names

```
def f(x, y):
return g(x)
def g(a):
return a + y
f(1, 2) # crashes because the variable y doesn't exist in
# the function g, whose parent is GLOBAL, and
# there is no y in the GLOBAL frame either!
```

An environment is a sequence of frames.

## Lambda Expressions

```
square = lambda x: x * x
# The above expression is equivalent to the below expression
def square(x):
return x * x
# Easily create functions on the go
apply_twice(lambda x: x + 1, 3)
```

However, lambda expressions can only be of one line -- a return statement. This means that they're only useful for simple, one-line expressions.

Lambda functions are always pure functions unless they call impure functions.

## Function Composition

```
def square(x):
return x * x
def triple(x):
return 3 * x
def compose(f, g):
def h(x):
return f(g(x))
return h
squiple = compose(square, triple)
# squiple(2) = 36
tripare = compose(triple, square)
# tripare(2) = 12
```