Lab 2: Lambdas and Higher-Order Functions

Starter Files

Download lab02.zip.
Inside the archive, you will find starter files for the questions in this lab,
along with a copy of the OK autograder.

Submission

By the end of this lab, you should have submitted the lab with
python3 ok --submit. You may submit more than once before the
deadline; only the final submission will be graded.

Questions 1, 2, 3, and 4 must be completed in order to receive credit for
this lab. Starter code for questions 3 and 4 is in lab02.py.

Question 5 (What Would Python Display?) is optional. It is recommended
that you work on this should you finish the required section early, or if you
are struggling with the required questions.

Questions 6, 7, and 8 are optional. It is recommended that you complete
these problems on your own time. Starter code for questions 7 and 8 is in
lab02_extra.py.

Topics

Consult this section if you need a refresher on the material for this lab. It's
okay to skip directly to the questions and refer back
here should you get stuck.

Lambdas

Lambda expressions are one-line functions that specify two things:
the parameters and the return value.

lambda <parameters>: <return value>

While both lambda and def statements are related to functions, there are some differences.

lambda

def

Type

lambda is an expression

def is a statement

Description

Evaluating a lambda expression does not create or modify any variables.
Lambda expressions just create new function values.

Executing a def statement will create a new function value and bind it to a variable in the current environment.

Example

lambda x: x * x

def square(x):
return x * x

A lambda expression by itself is not very interesting. As with any values
such as numbers, Booleans, strings, we usually:

assign lambdas to variables (foo = lambda x: x)

pass them in to other functions (bar(lambda x: x))

Higher Order Functions

A higher order function is a function that manipulates other functions by taking
in functions as arguments, returning a function, or both. We will be exploring
many applications of higher order functions.

Required Questions

What Would Python Display? (Part 1)

Question 1: WWPD: Lambda the Free

Use OK to test your knowledge with the following "What Would Python Display?"
questions:

python3 ok -q lambda -u

Hint: Remember for all WWPD questions, input Function if you believe the
answer is <function...>, Error if it errors, and Nothing if nothing
is displayed.

Coding Practice

Question 3: Lambdas and Currying

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 or refer to the
textbook
if you're not sure what this means.

Question 4: Composite Identity Function

Write a function that takes in two single-argument functions, f and g, and
returns another function that has a single parameter x. The returned
function should return True if f(g(x)) is equal to g(f(x)). You can
assume the output of g(x) is a valid input for f and vice versa.
You may use the compose1 function from lecture, re-defined below.

The implementations look quite similar! Generalize this logic by writing a
function count_cond, which takes in a two-argument predicate function condition(n,
i). count_cond returns a one-argument function that counts all the numbers
from 1 to n that satisfy condition.

Question 8: I Heard You Liked Functions...

Define a function cycle that takes in three functions f1, f2,
f3, as arguments. cycle will return another function that should
take in an integer argument n and return another function. That
final function should take in an argument x and cycle through
applying f1, f2, and f3 to x, depending on what n
was. Here's the what the final function should do to x for a few
values of n:

n = 0, return x

n = 1, apply f1 to x, or return f1(x)

n = 2, apply f1 to x and then f2 to the result of that, or
return f2(f1(x))

n = 3, apply f1 to x, f2 to the result of applying f1,
and then f3 to the result of applying f2, or f3(f2(f1(x)))

n = 4, start the cycle again applying f1, then f2, then f3,
then f1 again, or f1(f3(f2(f1(x))))