1
(define wadd (lambda (i L)
                (if (null? L) 0
                    (+ i (car L)))
                    (set! i (+ i (car L)))
                          (set! L (cdr L))))

(wadd 9 '(1 2 3))

这不返回任何内容。我期望它会这样做(3 + (2 + (9 + 1)),这应该等同于15. 我使用set!错误的方式吗?我不能set!在一个if条件内打电话吗?

4

2 回答 2

3

我从您的代码中推断出您打算以某种方式遍历列表,但是在wadd迭代列表的过程中没有任何内容 - 没有递归调用,没有循环指令,什么都没有:只是一个误用的条件和几个set!只执行一次的 s . 我不会尝试修复问题中的程序,无法修复 - 我宁愿向您展示解决问题的正确方法。你想要一些类似的东西:

(define wadd
  (lambda (i L)
    (let loop ((L L)
               (acc i))
      (if (null? L)
          acc
          (loop (cdr L) (+ (car L) acc))))))

执行时,前面的过程将评估这个表达式:(wadd 9 '(1 2 3))就像这样: (+ 3 (+ 2 (+ 1 9)))。请注意,正如@Maxwell 所指出的,上述操作可以使用foldl更简洁地表达:

(define wadd
  (lambda (i L)
    (foldl + i L)))

作为一般规则,在 Scheme 中,您不会set!像在命令式、类 C 语言中那样频繁地使用赋值(指令)——首选函数式编程风格,它严重依赖递归和不使用的操作变异状态。

于 2013-01-09T04:59:56.777 回答
2

我认为如果你修复你的缩进,你的问题会变得更加明显。

该函数set!返回<#void>(或类似的虚无)。您的 lambdawadd执行以下操作:

  1. 检查是否L为 null,并评估为 0 或i+ (car L),然后丢弃结果。
  2. 修改i并评估为空
  3. 修改L不返回

如果您将多个语句放在一个 lambda 中,它们会begin显式地包装在一个语句中:

(lambda () 1 2 3) => (lambda () (begin 1 2 3))

begin一个序列中多个表达式的语句中,整个表达式的begin计算结果为最后一个语句的结果:

(begin 1 2 3) => 3
于 2013-01-09T03:44:50.543 回答