# 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]
return n + k

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``````