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() ________________

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 = ________________

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 argument. >>> x = mul_by_num(5) >>> y = mul_by_num(2) >>> x(3) 15 >>> y(-4) -8 """ 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) 8 """ return ________________________________________

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 b(y) _________ def c(x): y = a(x) return b(x) + a(x+y) c(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) f(2) _________ g = lambda x: x * x f(3) _________