题
我现在正在学习SICP,并执行EX2.23我已经为以下代码而努力:
(define (for-each proc items)
(if (null? items)
#t
((proc (car items))
(for-each proc (cdr items)))))
但运行时,出现错误: 程序申请:预期程序,给定:#;论据是:()
我想我知道原因:我递归地调用 for-each 函数,每个调用的 for-each 都想要返回值
但是当我修改了代码后:
(define (for-each proc items)
(cond ((null? items) #t)
(else (proc (car items)) (for-each proc (cdr items)))))
它运行良好。我不明白,为什么?在 条件, ,每个调用for-each都不需要返回值吗?
我使用了 DrScheme,并选择语言 SICP
我的母语不是英语,所以如果有什么没有描述清楚的地方,请告诉我
解决方案
但运行时,出现错误:程序申请:预期 > 程序,给定:#;论据是:()
我想我知道原因:我递归地调用 for-each 函数,> 每个调用的 for-each 都想要返回值
不,这是因为在替代条款中 if
你有这个组合 ((proc (car items)) (for-each proc (cdr items)))
. 。您打算评估这两种组合 (proc (car items))
和 (for-each proc (cdr items))
顺序地,为此你认为将它们放在另一对括号中会起作用。但实际上,您指定的是结果 (proc (car items))
是一个应用于参数的过程,该参数是以下参数的返回值 (for-each proc (cdr items))
. 。情况并非如此,并且您会收到错误。关键是Lisp中的括号不是为了分组,而是有一定的意义。
问题是 if
该位置只能有一个组合,而您希望连续有两个组合。另一方面, cond
不受此类限制;您可以将尽可能长的单个组合序列放入一个的后续部分 cond
条款如您所愿。这种情况就是语言被定义为如何工作的。
你也可以使用 cond
在这些情况下,但如果您仍然想使用 if
有一些选项可以将多种组合填充到一个组合中。E.G。您可以创建一个 lambda 过程,其主体是这两个组合并立即将其关闭:
(define (for-each proc items) (if (null? items) #t ((lambda () (proc (car items)) (for-each proc (cdr items)) )) ))
或者你可以使用 begin
这实际上是用于这样的目的:
(define (for-each proc items) (if (null? items) #t (begin (proc (car items)) (for-each proc (cdr items)) ) ))