您展示的问题也可以通过这种方式解决。
def cons(a, b):
return (a,b)
def car(pair):
return pair[0]
def cdr(pair):
return pair[1]
这是你将如何使用它:
lst = cons(1,cons(2,3))
# Get the first element of lst
print(car(lst))
# Get the second element of lst
print(car(cdr(lst)))
# Get the last element of lst
print(cdr(cdr(lst)))
输出:
1
2
3
我只是展示这一点,以便您可以看到解决该问题的方法不止一种,而您发现的方法很少在 python 中完成。任何想在 python 中解决这个问题的人都会在 99% 的时间里按照我在这里展示的方式去做。
现在谈谈你的问题。
def cons(a, b):
def pair(f):
return f(a, b)
return pair
def car(f):
def pair(a,b):
return a
return f(pair)
def cdr(f):
def pair(a, b):
return b
return f(pair)
首先让我们使用一些 haskell 函数符号来讨论这些函数,以便您可以看到这些函数的完整类型:
cons::(a, b) -> (((a, b) -> c) -> c)
cons是一个接受两个参数的函数a,b然后它返回一个函数,该函数f接受另一个函数,当给定参数 ( a, b) 时,返回c,其中c可能是aorb或其他东西。f然后返回 的值c。
多嘴啊!
另一种思考方式是,返回的函数f( ((a, b) -> c) -> c)cons用于转发a和转发b给任何想要对 a 进行操作的运算符(或映射函数)cons。此运算符返回c. f然后 simple 返回此映射函数返回的任何内容,恰好是c.
现在不用担心是什么c。只需将其视为将函数应用于 a 的结果cons。
car::(((a, b) -> a) -> a) -> a
car定义一个从(a,b)to的可能映射,并返回使用此映射c调用的值。f
car接受一个f想要从输入映射(a,b)到某个输出的函数c。在这种情况下,car将映射定义为这意味着传递给的(a, b) -> a任何函数都将返回 的第一个参数,即. 这就是将要返回的东西。fcar(a,b)acar
cdr::(((a, b) -> b) -> b) -> b
类似于,但由返回而不是car定义的映射。cdrba
注意 和 的输入cdr与返回car的函数 ( f)有多么相似cons?这就是为什么我只是调用他们的输入f
现在回答你的一些问题:
cdr(cons(3, 4)): 这两个函数的评估顺序是什么?我通常会认为cons(3, 4)首先评估它,但在这种情况下这没有意义,因为cons(3, 4)返回一个函数,其中参数 3 和 4 是“集成的”,所以没有办法挑选出参数。
根据我上面给出的解释,从返回的函数cons与cdr. 现在所cdr要做的就是提供一个映射函数f并返回任何f返回值。
在我看来,car(f)返回一个函数,那么如何cons(3, 4)返回3?编辑:错字,应该car(cons(3, 4))代替cons(3, 4)
car(f)不一定返回函数。请参阅上面的类型签名。它只返回返回的任何内容f,如果它恰好是一个函数,那么它将返回一个函数。
通常,car返回 a 的第一个元素cons。在这种情况下,由于cons(3,4)返回一个函数 ( f) 并且此函数被传递给car,然后car将向此函数提供另一个函数,该函数选择它的第一个参数,3在这种情况下。这3是现在的结果car(cons(3,4)。
我希望这能解决问题。