【问题标题】:How does Scheme return the "built up" value of a recursive procedure after the base case is met?满足基本情况后,Scheme 如何返回递归过程的“构建”值?
【发布时间】:2014-03-03 04:11:09
【问题描述】:

我正在浏览Simply Scheme 并刚刚进入递归部分。

我不明白为什么当满足基本情况时,Scheme 返回递归过程的“构建”值,而不是导致基本情况评估为#t 的实际参数值。

例如,看看这个递归过程的示例代码 sn-p,它将一个单词作为输入,将其反转,然后将其吐回:

(define (reverse wd)
  (if (empty? wd) wd
      (word (last wd) (reverse (bl wd)))))

这让我感到困惑:(if (empty? wd) wd

我了解,当形参 wd 的实际参数值为空(或 "")时,基本情况的计算结果为 #t,导致 if 的第二个参数的值被计算。

理解的是if(在这种情况下为wd)的第二个参数如何返回一个非空的东西,即使它看起来是一样的,触发基本情况的空的形式参数。

我错过了什么?

如果文档(或文本)中有解释这一点的内容,我很乐意查看它。

【问题讨论】:

  • 为了清楚(可能已经很清楚),如果test 为真,(if test then-part else-part) 的值为then-part,如果test 为假,else-part 的值。因此,每当wd 为空时,您将返回wd(为空)。但是,只要wd为空,您就会返回(word (last wd) (reverse (bl wd)))。当wd 不为空时,您知道为什么它不会为空吗?即使不考虑(reverse (bl wd)),只看(word (last wd) …),我们也会看到一些非空的东西,因为(last wd)something,而(word <something> …) 是一个以<something> 开头的字符串。
  • @JoshuaTaylor - 是的,我明白了。 Sylwester 和 Chris Jester-Young 帮助确定了以下 cmets 的最终点。欢迎您的贡献。

标签: recursion scheme mit-scheme


【解决方案1】:

由于这里的状态没有改变,你可以用它的递归替换函数所做的事情。想象一下,你有一个两个字母的单词a

(reverse a) ; =>
(word (last a) (reverse (bl a))) ; ==>
(word (last a) (word (last (bl a)) (reverse (bl (bl a))))) ; ==>
(word (last a) (word (last (bl a)) (bl (bl a)))) ; ==>
(word (last a) (word (last (bl a)) '()))

最后一个(bl (bl a)) 是最后一次迭代所做的唯一事情,它是'()。 其余的将作为先前调用的延续完成。

编辑

澄清一下..想象a是“ab”

(reverse "ab") ; turns into
(word (last "ab") (reverse (bl "ab")))           ; tuns into
(word "b" (reverse (bl "ab")))                   ; turns into 
(word "b" (reverse "a")))                        ; turns into 
(word "b" (word (last "a") (reverse (bl "a"))))) ; turns into
(word "b" (word "a" (reverse ""))))

现在看看最后一个.. 当(reverse "") 返回 "" 时,它是在上一个表单调用中使用的结果,在word 表单中,所以你会得到(word "a" "") ==> "a",然后返回到第一个调用(word "b" "a")。这些是续集。

【讨论】:

  • 谢谢,但我还是有心理障碍。 :) 具体来说,我只是没有看到(empty? wd) wd 中第一个wd 的值如何可能是'(),但第二个不是。您能否在答案中包含一些关于此的内容?
  • 编辑:我应该为空字写""而不是'()
  • @d3vin 在基本情况下它是空的并且返回是空的。 (reverse "") ==> ""。其结果将是上一轮的第二个参数。因此,“q”将进行两次迭代,最终为 (word (last "q" (reverse "")) => (word (last "q") "")
  • WRT这一点:The result for that would then be the second argument in the previous round.我不相信文中解释了这个“动作”,因此我不知道相应的技术细节或相关术语。我相信现在我可以自己找到详细的技术解释(谢谢,顺便说一句),但是如果您想在答案中添加一两个“面包屑”,这可能对我和其他人将来有所帮助。 :)
  • 阅读Scheme对延续的具体化让我更加清楚这一点。我目前正在阅读关于wikipediascheme.com 的续集。如果您知道更好的资源,请随时告诉我。谢谢!
【解决方案2】:

关键的见解是它为基本情况返回空。那是因为空字符串的反面一个空字符串。

递归案例实际上是基于该假设的。换句话说,这就是您的 reverse 函数的工作原理:

  1. 如果给定单词​​为空,则返回空。
  2. 否则,从单词中取出最后一个字母,并将其与单词其余部分的反面连接起来。

示例。假设我们正在反转“Devin”:

  • 单词“Devin”不为空,因此我们将“n”与“Devi”的倒数连接起来。
    • “Devi”这个词不为空,所以我们将“i”与“Dev”的反义词连接起来。
      • “Dev”一词不为空,因此我们将“v”与“De”的反面连接起来。
        • 单词“De”不为空,因此我们将“e”与“D”的倒数连接。
          • 单词“D”不为空,因此我们将“D”与“”的反面连接起来。
            • 单词“”是空的,所以我们返回“”。
          • 这里,我们返回 "D" 和 "",即 "D"。
        • 这里,我们返回“e”和“D”,即“eD”。
      • 在这里,我们返回“v”与“eD”,即“veD”。
    • 在这里,我们返回与“veD”连接的“i”,即“iveD”。
  • 在这里,我们返回与“iveD”连接的“n”,即“niveD”。

【讨论】:

  • Juster-Young - 从视觉上看,这很有意义(谢谢,顺便说一句)。在回应@Sylwester 上面的评论时,我提到缺乏知识 WRT(根据您的回答)The word "" is empty, so we return "". 之后会发生什么。你有什么可以补充的吗?
  • 然后,你上一层,我说的“D”这个词不为空,所以我们将“D”的反面加入“D”,正如我们已经确定的那样,是“”。因此,上一级的结果是“D”与“”连接,即“D”。
猜你喜欢
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 2015-03-26
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
相关资源
最近更新 更多