Environments - Fri, Sep 6

Environments for Higher-Order Functions

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

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.

How to Draw an Environment Diagram

When a function is called:

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