CS61A Lab 2a: Lambdas

Week 2a, Summer 2013

Exercise 1: Understanding Lambdas

Now, we will visit the idea of lambda functions. These are functions that are one line, and that line just specifies the return value. The format of a lambda function is as follows:

lambda [parameters]: [return value]

One of the differences between using the def keyword and lambda expressions which we would like to point out is that def is a statement, while lambda is an expression. Evaluating a def statement will have a side effect; namely, it creates a new function binding in the current environment. On the other hand, evaluating a lambda expression will not change the environment unless we do something with this expression. For instance, we could assign it to a variable or pass it in as a function argument.

Another bit of syntax that we introduce in this exercise is the conditional expression. It has the following format:

[true-value] if [conditional] else [false-value]

It is almost equivalent to the if statement that you have already seen. If the conditional evaluates to True then the entire expression evaluates to [true-value]. If the condition evaluates to false, then the entire expression evaluates to [false-value].

Knowing this, fill in the blanks as to what Python would do here:

>>> doctor = lambda : "who"
# Q1
>>> doctor()
>>> ninth = lambda x: "Fantastic!" if x == 9 else tenth
>>> tenth = lambda y: "Allons-y!" if y == 10 else eleventh
>>> eleventh = lambda z: "Geronimo!" if z == 11 else ninth
# Q2
>>> ninth(9)
# Q3
>>> ninth(2)(10)
# Q4
>>> tenth(10)
# Q5
>>> tenth(12) is eleventh
# Q6
>>> eleventh(10)(11)(9)(11)
# Q7: Troy revisited, but with lambdas!
>>> def Troy():
...  abed = 0
...  while abed < 10:
...    britta = lambda: abed
...    abed += 1
...  abed = 20
...  return britta
>>> jeff = Troy()
>>> shirley = lambda : jeff
>>> pierce = shirley()
>>> pierce()

Exercise 2: Lambda'ed Strategies

Recall the following function definitions from Lab 1b. The default strategy always returns 5:

def default_strategy(score, op_score):
    return 5

A strategy maker is a function that defines a strategy within its body, and returns the resulting strategy. We had defined a strategy maker that returns the default strategy:

def make_default_strategy():
    def default_strategy(score, op_score):
        return 5
    return default_strategy

You then implemented make_weird_strategy, another strategy maker:

def make_weird_strategy(num_rolls):
    def weird_strategy(score, op_score):
        return max(num_rolls, (score+op_score)//20)
    return weird_strategy

As an exercise, implement all 3 of these functions in one line each, using lambda expressions.

>>> default_strategy = ________________
>>> make_default_strategy = _________________
>>> make_weird_strategy = ________________

Exercise 3: Lambdas and Currying

Using a lambda function, complete the mul by num function. This function should take an argument and return a one argument function that multiplies any value passed to it by the original number. Its body must be one line long:

def mul_by_num(num):
    Returns a function that takes one argument and returns num times that
    >>> x = mul_by_num(5)
    >>> y = mul_by_num(2)
    >>> x(3)
    >>> y(-4)
    return ________________________________________

We can transform multiple-argument functions into a chain of single-argument, higher order functions by taking advantage of lambda expressions. This is useful when dealing with functions that take only single-argument functions. We will see some examples of these later on.

Write a function lambda_curry2 that will curry any two argument function using lambdas. See the doctest if you're not sure what this means.

def lambda_curry2(func):
    Returns a Curried version of a two argument function func.
    >>> x = lambda_curry2(add)
    >>> y = x(3)
    >>> y(5)
    return ________________________________________

Exercise 4: Environment Diagrams

Try drawing environment diagrams for the following code and predicting what Python will output:

# Q1
a = lambda x : x * 2 + 1

def b(x):
    return x * y

y = 3

def c(x):
    y = a(x)
    return b(x) + a(x+y)

# Q2: This one is pretty tough. A carefully drawn environment diagram will be really useful.
g = lambda x: x + 3

def wow(f):
    def boom(g):
    	return f(g)
    return boom

f = wow(g)
g = lambda x: x * x