如何从 Scheme 中的递归调用中正确 return 值?
How to properly return value from a recursive call in Scheme?
我的目标是为 plus-minus
方法提供一个列表,以便它可以遍历所有可能的情况,在这种情况下,如果任何给定数量的元素都为负数,然后从剩余正数的总和中减去numbers 有可能在原始列表中找到或找不到该数字。
例如:如果我们向 plus-minus
提供 (3 1 2) 的列表,那么 plus-minus
应该 return #t
一旦达到 (3 1 -2 ), 因为 4 - 2 = 2 并且 2 在 (3 1 2) 的原始列表中。
我有一个独立于plus-minus
、ref-check
的方法,用于判断目标号码是否在列表中。因此,在提供的示例中,它的工作是确定 2 是否存在于 (3 1 2) 的原始列表中。因为它确实存在于原始列表中,所以 ref-check
是 return 1
for #t
.
我目前的问题是 ref-check
确实 return #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
编辑:正确和清晰
让我们开始回答问题:
My issue currently is that ref-check
does return #t
[1
] back to plus-minus
, but the method seems to continue regardless.
如果 ref-check
returns 1
到您的调用函数,进一步的递归调用 不会 从当前调用堆栈进一步向下。所以,在 ref-check
returned 之后,调用 plus-minus
also returns.
但是它return调用它的函数,可能是"you"(即顶层),但 更有可能 将是 "itself"。一个例子可能会更好地说明这一点:
让我们调用 (plus-minus '(3 1 2) 0 0)
:这将登陆 cond
的 else
分支,首先调用 (plus-minus '(1 2) 3 0)
。这也将落在 else
分支中,因此首先调用 (plus-minus '(2) 5 0)
(最终将 return #f
,因此我们忽略它)然后 (plus-minus '(2) 3 1)
.在 that 对 plus-minus
的调用中,由于 [=11],它将到达 returns #t
的 cond
的分支=](3-1 == 2
是 (1 2)
的一部分)。函数 returns 到它的调用者,实际上是 "in the else
branch" 第一次调用 plus-minus
。在那里,您丢弃 returned 值,并无条件地调用 (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)
;; ...
要摆脱这种情况,您需要进行第二次递归调用 仅 如果第一个还没有 return #t
。这可以通过将两个调用包装在 (or ...)
.
中轻松实现
[..] how I ensure ref-check always receives the original list,
每次调用 plus-minus
.
时将原始列表作为附加参数向下传递
(3 1 2 400)
should always return #f
按照你现在的逻辑,那不会发生。由于您调用 ref-check
也使用部分计算的 sum1
和 sum2
(即不是列表中的所有元素 "decided" 但无论它们是否为负数)以上将产生 #t
.
要获得所需的行为,您需要在列表的所有元素都添加到 sum1
或 [=45] 时仅调用 ref-check
=],因此当没有更多元素要处理时,即当列表为空时。
现在,一些评论:
- 不要用
0
和1
来表示真实性,在Scheme中你应该用#f
来表示false
和其他任何东西(#t
如果你不能有意义地 return 任何东西)对于 true
.
- 缩进和间距:你真的应该遵守这里既定的标准。通常情况下,您的编辑器应该会处理这个问题。
- 别说"methods"。它被称为函数。
我没有提供 "final working" 代码让您自己实施上述修复。
我的目标是为 plus-minus
方法提供一个列表,以便它可以遍历所有可能的情况,在这种情况下,如果任何给定数量的元素都为负数,然后从剩余正数的总和中减去numbers 有可能在原始列表中找到或找不到该数字。
例如:如果我们向 plus-minus
提供 (3 1 2) 的列表,那么 plus-minus
应该 return #t
一旦达到 (3 1 -2 ), 因为 4 - 2 = 2 并且 2 在 (3 1 2) 的原始列表中。
我有一个独立于plus-minus
、ref-check
的方法,用于判断目标号码是否在列表中。因此,在提供的示例中,它的工作是确定 2 是否存在于 (3 1 2) 的原始列表中。因为它确实存在于原始列表中,所以 ref-check
是 return 1
for #t
.
我目前的问题是 ref-check
确实 return #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
编辑:正确和清晰
让我们开始回答问题:
My issue currently is that
ref-check
does return[#t
1
] back toplus-minus
, but the method seems to continue regardless.
如果 ref-check
returns 1
到您的调用函数,进一步的递归调用 不会 从当前调用堆栈进一步向下。所以,在 ref-check
returned 之后,调用 plus-minus
also returns.
但是它return调用它的函数,可能是"you"(即顶层),但 更有可能 将是 "itself"。一个例子可能会更好地说明这一点:
让我们调用 (plus-minus '(3 1 2) 0 0)
:这将登陆 cond
的 else
分支,首先调用 (plus-minus '(1 2) 3 0)
。这也将落在 else
分支中,因此首先调用 (plus-minus '(2) 5 0)
(最终将 return #f
,因此我们忽略它)然后 (plus-minus '(2) 3 1)
.在 that 对 plus-minus
的调用中,由于 [=11],它将到达 returns #t
的 cond
的分支=](3-1 == 2
是 (1 2)
的一部分)。函数 returns 到它的调用者,实际上是 "in the else
branch" 第一次调用 plus-minus
。在那里,您丢弃 returned 值,并无条件地调用 (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)
;; ...
要摆脱这种情况,您需要进行第二次递归调用 仅 如果第一个还没有 return #t
。这可以通过将两个调用包装在 (or ...)
.
[..] how I ensure ref-check always receives the original list,
每次调用 plus-minus
.
(3 1 2 400)
should always return#f
按照你现在的逻辑,那不会发生。由于您调用 ref-check
也使用部分计算的 sum1
和 sum2
(即不是列表中的所有元素 "decided" 但无论它们是否为负数)以上将产生 #t
.
要获得所需的行为,您需要在列表的所有元素都添加到 sum1
或 [=45] 时仅调用 ref-check
=],因此当没有更多元素要处理时,即当列表为空时。
现在,一些评论:
- 不要用
0
和1
来表示真实性,在Scheme中你应该用#f
来表示false
和其他任何东西(#t
如果你不能有意义地 return 任何东西)对于true
. - 缩进和间距:你真的应该遵守这里既定的标准。通常情况下,您的编辑器应该会处理这个问题。
- 别说"methods"。它被称为函数。
我没有提供 "final working" 代码让您自己实施上述修复。