【问题标题】:Procedure As Argument - Scheme过程作为参数 - 方案
【发布时间】:2017-03-08 07:31:59
【问题描述】:
我正在使用以下一组方案定义。我的问题专门关于“尾巴”功能。额外的一组括号做什么使函数期望一个过程作为参数而不是一个列表,如果有一组括号就会出现这种情况?
(define (make-stream n f)
(define (next m)
(cons m (lambda () (next (f m)))))
(next n))
(define head car)
(define (tail stream)
((cdr stream)))
(define (nth stream n)
(if (= n 0) (head stream)
(nth (tail stream) (- n 1))))
(define even (make-stream 0 (lambda (n) (+ n 2))))
抱歉,如果此问题的格式不正确或其他不恰当的问题,我正在尝试学习如何使用该网站。
【问题讨论】:
标签:
functional-programming
scheme
lisp
【解决方案1】:
我的问题是关于“尾巴”功能的。额外的一组括号做什么使函数期望一个过程作为参数而不是一个列表,如果有一组括号就会出现这种情况?
这是你的程序
(define (make-stream n f)
(define (next m)
(cons m (lambda () (next (f m)))))
(next n))
我们先看看car和cdr会返回什么
(car (make-stream 0 f) ; => 0
(cdr (make-stream 0 f) ; => (lambda () (next (f m)))
car 返回的这个无效(零参数)过程称为Thunk。它通常用于延迟计算的评估。在这种情况下,它用于防止 make-stream 在提供 make-stream 的两个参数后立即无限递归。
为了得到下一个值,我们所要做的就是应用 thunk。这次注意多余的括号
((cdr (make-stream 0 f))) ;=> (next (f m))
这就是为什么你看到...
(define (tail stream) ((cdr stream)))
...这将返回下一个cons,而不是...
(define (tail stream) (cdr stream))
...这将返回一个包含下一个cons的thunk
【解决方案2】:
在scheme中,表达式使用s-表达式的第一个参数作为使用以下参数进行评估的方法。
例如:
(+ 1 2)
它将+ 应用于 1 和 2。
如果我们把例子复杂一点,我们可以做这样的事情。
(if (> x y) + -)
这里的表达式将返回+ 符号或-。我们可以进一步改变这个表达式……用这个:
((if (> x y) + -) 1 2)
这里if 表达式将返回+ 或- 函数,该函数稍后将应用于1 和2。
现在回到你的方法!
(define (tail stream)
((cdr stream)))
如您所见,您有双括号。这意味着它将应用位于stream 的cdr 中的函数。就这么简单。
如果我们查看您的构造函数以获取流,我们可以看到您的构造函数实际上返回了一个以 lambda 函数作为第二个成员的对。
make-stream 的第二个参数是一个被调用以生成下一个数字的函数。 f 方法不必与每个 next 调用一起传递,因为它在作用域中可用。