那么,这是否意味着 (lambda (x y) (cons (p x) y)) 是“操作”部分?
是的。
& 如果是,x 和 y 是什么以及它们是如何传递到方程中的?
x 是“当前元素”,y 是“递归调用列表其余部分的(accumulate ...) 的结果”。 p>
这就是这个意思。每个给定的列表都被视为一对缺点 - 一对 car 和 cdr。列表的car 的值进入x,cdr 的值进入递归调用,其结果进入y。或以等式风格,
accumulate( op, z, CONS(e,es) ) = op( e, accumulate(op, z, es) )
其中CONS(e,es) 不是函数调用,而是数据表示(使用大写来表示这一点)- cons 单元格 在其car 和e 中带有car 和es (阅读:eez,如 e,复数)在其cdr 中。所以当op(x,y) = ...被调用时,x = e和y = accumulate(op, z, es)被传入其中。
上面的等式定义了函数accumulate。对于NIL case,还需要一个等式:
accumulate( op, z, NIL ) = z
因此假设op是一个二元运算(即接收两个参数),能够处理accumulate的结果作为它的第二个参数。这种列表处理模式被称为"folding",或“catamorphism” - 即处理数据向下,将数据分析为其组成部分,并以某种方式重新组合它们,以某种方式安排二进制操作的“调用协议”。
还有其他模式,例如所谓的“变形”,
accumulate2( op, z, NIL ) = z
accumulate2( op, z, CONS(e,es) ) = op( e, es, accumulate2(op, z, es) )
这里假设操作是三元的(即接收三个参数),接收当前元素,输入列表的其余部分,以及输入列表其余部分的递归处理结果。它在实现需要访问输入和输出的数据处理模式时很有用(有时神秘地称为“吃蛋糕也吃蛋糕”)。
为了更有用,这些定义需要编码lazily,因此op 可以选择是否强制递归结果,以便能够提前中止(参见例如this)。