这是我相信你们中的许多人都熟悉的 SICP 书中的内容。这是本书中的一个早期示例,但我觉得一个非常重要的概念,我还无法理解。这里是:
(define (cons x y)
(define (dispatch m)
(cond ((= m 0) x)
((= m 1) y)
(else (error "Argument not 0 or 1 - CONS" m))))
dispatch)
(define (car z) (z 0))
(define (cdr z) (z 1))
所以在这里我明白
car
和 cdr
正在cons
范围内定义,我知道他们映射了一些参数 z
分别为 1 和 0(参数 z
是一些 cons
)。但是假设我调用(cons 3 4)
...当我们立即进入这个内部过程 dispatch
时,如何评估参数 3 和 4这需要一些参数m
我们还没有指定?而且,也许更重要的是,返回 ' dispatch
有什么意义? ?我根本不明白那部分。任何帮助表示赞赏,谢谢!
最佳答案
这是在 Scheme 中利用一等函数的最奇怪的(也可能是更精彩的)示例之一。 Little Schemer 中也有类似的东西,这是我第一次看到它的地方,我记得为它挠了好几天头。让我看看我是否可以用有意义的方式解释它,但如果不清楚,我很抱歉。
我假设你理解原语 cons
, car
, 和 cdr
因为它们已经在 Scheme 中实现了,但只是提醒您:cons
构造一对,car
选择对的第一个组件并返回它,cdr
选择第二个组件并返回它。以下是使用这些函数的简单示例:
> (cons 1 2)
(1 . 2)
> (car (cons 1 2))
1
> (cdr (cons 1 2))
2
cons
的版本, car
, 和 cdr
您粘贴的内容应该完全相同。我会试着告诉你怎么做。首先,
car
和 cdr
未在 cons
范围内定义.在您的代码片段中,所有三个( cons
、 car
和 cdr
)都在顶层定义。函数dispatch
是唯一在 cons
中定义的.函数
cons
接受两个参数并返回一个参数的函数。重要的是这两个参数对内部函数 dispatch
可见。 ,这就是返回的内容。一会儿我会讲到的。正如我在提醒中所说,
cons
构造一对。这个版本的cons
应该做同样的事情,但它返回一个函数!没关系,我们并不真正关心这对是如何在内存中实现或布局的,只要我们能得到第一个和第二个组件。所以有了这个新的基于函数的对,我们需要能够调用
car
并将该对作为参数传递,并获取第一个组件。在 car
的定义中,此参数称为 z
.如果您要使用这些新的 cons
执行我上面的相同 REPL session , car
, 和 cdr
函数,参数 z
在 car
将绑定(bind)到基于函数的对,即 cons
返回,即 dispatch
.这很令人困惑,但只要仔细考虑一下,你就会明白。基于
car
的实现, 似乎它采用一个参数的函数,并将其应用于数字 0
.所以它正在申请dispatch
至0
,从 dispatch
的定义中可以看出,这就是我们想要的。 cond
里面比较m
与 0
和 1
并返回 x
或 y
.在这种情况下,它返回 x
,这是 cons
的第一个参数,换句话说,该对的第一个组件!所以car
选择第一个组件,就像在 Scheme 中的普通原语一样。如果您对
cdr
遵循相同的逻辑,您会看到它的行为方式几乎相同,但将第二个参数返回到 cons
, y
,这是该对的第二个分量。有几件事可以帮助您更好地理解这一点。一种是回到第 1 章中对求值替换模型的描述。如果你仔细而细致地遵循这个替换模型,并在一些非常简单的例子中使用这些函数,你会发现它们是有效的。
另一种不那么乏味的方法是尝试使用
dispatch
直接在 REPL 上运行。下面,变量 p
被定义为引用 dispatch
cons
返回的函数.> (define p (cons 1 2))
#<function> ;; what the REPL prints here will be implementation specific
> (p 0)
1
> (p 1)
2
关于functional-programming - Scheme:返回另一个内部过程的过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12496482/