如何从Scheme中的递归调用中正确返回值?

时间:2016-04-24 06:24:49

标签: scheme lisp

我的目标是为plus-minus方法提供一个列表,以便它可以遍历每个可能的情况,如果任何给定数量的元素为负数,然后从剩余的正数之和中减去有可能在原始列表中找到或找不到该号码。

例如:如果我们向plus-minus提供(3 1 2)列表,那么plus-minus一旦到达(3 1 -2)就会返回#t,因为4 - 2 = 2和2在(3 1 2)的原始列表中。

我有plus-minus ref-check的单独方法,用于确定目标号码是否在列表中。因此,在提供的示例中,其作用是确定原始列表(3 1 2)中是否存在2。由于它确实存在于原始列表中,ref-check将为1返回#t

我目前的问题是ref-check确实将#t返回plus-minus,但该方法似乎无论如何都会继续。

我觉得这个问题有一个简单的解决方案。

工作代码:

;returns true if the element is in the list otherwise false
(define ref-check(lambda (list element)
            (cond
             ((null? list) 0)
             ((= element (car list)) 1)
             (else (ref-check (cdr list) element)))))


;main calculation
(define plus-minus(lambda (L sum1 sum2)
                    (cond
                      ((null? L) #f)
                      ((= (ref-check L (- sum1 sum2)) 1) #t)
                      (else (plus-minus (cdr L) (+ sum1 (car L)) sum2)
                            (plus-minus (cdr L) sum1 (+ sum2 (car L)))))))

示例输入:(plus-minus '(7 5 1 2) 0 0) 示例结果:#t

编辑:正确和清晰

1 个答案:

答案 0 :(得分:2)

让我们开始回答问题:

  

我目前的问题是ref-check确实将 #t [1]返回plus-minus,但该方法似乎仍在继续。

如果ref-check向您的呼叫功能返回1,则进一步的递归呼叫不会 从当前呼叫堆栈进一步向下< / em>的。因此,在ref-check返回后,调用plus-minus 也会返回

但是它返回到调用它的函数,可能是&#34;你&#34; (即顶层)但更可能将是&#34;本身&#34;。一个例子可能会更好地说明:

致电(plus-minus '(3 1 2) 0 0):这将会落在else的{​​{1}}分支,首先呼叫cond。它也将落在(plus-minus '(1 2) 3 0)分支中,因此首先调用else(最终将返回(plus-minus '(2) 5 0),因此我们忽略它),然后#f。在那次 (plus-minus '(2) 3 1)的调用中,由于plus-minuscond,它会点击返回#t的{​​{1}}的分支成为ref-check)的一部分。该函数返回其调用者,实际上是3-1 == 2分支中的#34;&#34;第一次调用(1 2)。在那里,您丢弃返回的值,并无条件地调用else,这将进一步调用plus-minus(plus-minus '(1 2) 0 3)

直观地显示部分调用堆栈:

ref-check

要摆脱这种情况,如果第一次没有返回plus-minus,你需要进行第二次递归调用 。通过将两个调用包装在(plus-minus '(3 1 2) 0 0) ;; In else (plus-minus '(1 2) 3 0) ;; In else (plus-minus '(2) 5 0) ;; Details discarded, returns #f ;; <== #f ;; Discard #f from above, and call (plus-minus '(2) 3 1) ;; ref-check returned 1, so return #t ;; <== #t ;; <== #t ;; Still in the else, got #t, discard, then (plus-minus '(1 2) 0 3) ;; ...

中,可以轻松实现此目的
  

[..]我如何确保ref-check总是收到原始列表,

每次调用#t时,将原始列表作为附加参数传递。

  

(or ...)应始终返回plus-minus

根据您当前的逻辑,这不会发生。由于您还使用部分计算的(3 1 2 400)#f来调用ref-check(即不是列表中的所有元素&#34;已决定&#34;但他们是否为负面否定)以上将产生sum1

要获得所需的行为,当列表的所有元素都添加到sum2#t时,您需要仅调用ref-check ,因此没有更多要处理的元素,即当列表为空时。

现在,一些评论:

  • 请勿使用sum1sum2来表示真实性,您应该使用0代表1以及其他任何内容(#f如果你不能有意义地归还任何东西)false
  • 缩进和间距:您应该在这里遵守既定标准。通常情况下,您的编辑应该注意这一点。
  • 不要说&#34;方法&#34;。它被称为功能

我没有提供&#34;最终工作&#34;允许您自己实现上述修复的代码。