在UCB CS 61A的Homework 02中,有这样一个问题:
Question 4: Church numerals
def zero(f):
return lambda x: x
def successor(n):
return lambda f: lambda x: f(n(f)(x))
def one(f):
"""Church numeral 1: same as successor(zero)"""
"*** YOUR CODE HERE ***"
return lambda x: x
def two(f):
"""Church numeral 2: same as successor(successor(zero))"""
"*** YOUR CODE HERE ***"
return lambda x: f(x)
three = successor(two)
难以理解的那段代码为:
def successor(n):
return lambda f: lambda x: f(n(f)(x))
successor函数使用 lambda 返回匿名函数。这很难阅读,所以我们可以使用一个命名函数替换它。
def successor(n):
def inner_function_one(f):
def inner_function_two(x):
return f(n(f)(x))
return inner_function_two
return inner_function_one
所以现在我们已经分解了原函数,可以看到successor返回一个函数,而该函数又返回另一个函数,该函数返回…。 f(n(f)(x)) 让人很难阅读,其含义为函数f被参数 n(f)(x)调用,而n(f)返回一个函数传递参数x。让我们使用一些更具描述性的变量名称来查看此处发生的情况。
def successor(first_function):
def inner_function_one(second_function):
def inner_function_two(arg):
return second_function(first_function(second_function)(arg))
# Equivalent to something like
# return second_function(returned_function(arg))
# where returned_function is the result of
# first_function(second_function)
return inner_function_two
return inner_function_one
接下来题目又问道:
def add_church(m, n):
"""Return the Church numeral for m + n, for Church numerals m and n.
>>> church_to_int(add_church(two, three))
5
"""
"*** YOUR CODE HERE ***"
return lambda f: lambda x: m(f)(n(f)(x))
Church 编码可以理解为将函数重复应用于某个参数。所以要add m + n
,我们需要将函数 f
应用到参数 x
m + n
次,或者等效地应用它 n
次,然后应用它 m
次:
def add_church(m, n):
def m_plus_n(f):
def f_repeated_m_plus_n_times(x) # f ** (m + n)
intermediate_result = (n(f))(x) # (f ** n) (x)
final_result = (m(f))(intermediate_result) # (f ** m) ((f ** n) (x))
return final_result
return f_repeated_m_plus_n_times
return m_plus_n
使用 lambda 形式,删除多余的括号:
def add_church(m, n):
"""Return the Church numeral for m + n, for Church numerals m and n.
>>> three = successor(two)
>>> church_to_int(add_church(two, three))
5
"""
lambda f: lambda x: m(f)(n(f)(x))