javascript - Eloquent Javascript Book 第 5 章关于递归和祖先的示例

标签 javascript recursion

当我遇到这段关于总结祖先的代码时,正在浏览 Eloquent javascript 这本书。有几 block 板已经讨论了这个的不同部分,但我遇到麻烦的部分是这个 block :

var thisOneCounts = current != person && test ( current ); 

具体来说,什么时候 current 不是 == to person?我似乎找不到情况,因为当前总是被称为人。但显然我遗漏了一些东西,因为当我取出那段代码时,它会返回一个不同的解决方案。下面是完整的代码。

 function reduceAncestors(person, f, defaultVal) {
     function valueFor(person) {
         if (person == null)
             return defaultVal;
         else
             return f(person, valueFor(byName[person.mother]), valueFor(byName[person.father]));
     }
     return valueFor(person);

 }

 function countAncestors(person, test) {
     function combine(current, fromMother, fromFather) {
         var thisOneCounts = current != person && test(current); // **
         return fromMother + fromFather + (thisOneCounts ? 1 : 0);
     }
     return reduceAncestors(person, combine, 0);
 }

 function longLivingPercentage(person) {
     var all = countAncestors(person, function (person) {
         return true;
     });

     var longLiving = countAncestors(person, function (person) {
         return (person.died - person.born) >= 70;
     });
     return longLiving / all;
 }
 console.log(longLivingPercentage(byName["Emile Haverbeke"]));

最佳答案

请注意,reduceAncestors() 中的 valueFor() 函数是对原始人的 parent 递归调用的,然后是祖 parent 等。这些递归调用可能会使调用 f(),而 f() 是来自 countAncestors()combine() 函数。

因此,起始人物首先被传递给reduceAncestors()。这会调用 f()(即 combine() 内部函数),并使用父级调用 valueFor() 的结果。反过来,这将导致 mother 被传递给 f()father 被传递给 f()。回到最初调用 countAncestors() 的上下文中,person 仍然是 original person,但是 的传入值>currentcombine() 会有所不同(它将是母亲或父亲或外祖母/祖父或祖母/祖父等)。

让我们看看 longLivingPercentage() 函数中对 countAncestors() 的第一次调用。我们传入起始人物和始终返回 true 的虚拟 test()。我不知道代码期望家谱数据结构是什么,但我们假设它是这样的:

{
  person: "Bob",
  mother: {
    person: "Mary",
    mother: null,
    father: null
  },
  father: {
    person: "Jim",
    mother: null,
    father: null
  }
}

因此:

  1. 为 Bob 调用了 countAncestors() 函数。
  2. 将 Bob 传递给 reduceAncestors(),以及对该 combine() 函数的引用。
  3. reduceAncestors() 中,为 Bob 调用了 valueFor(),由于 Bob 不为空,我们调用了 f() — 即 combine() — 需要传递 Bob、母亲和父亲。
  4. 但是,在调用 f() 之前,我们需要用母亲和父亲调用 valueFor(),因为结果这些调用中的一部分需要传递给 f()
  5. 所以 valueFor() 是和妈妈一起调用的。 想调用f(),它需要检查母亲和父亲(即 Bob 的母亲的母亲和 Bob 的母亲)母亲的父亲)。
  6. 这两个祖 parent 调用很快就会失败,因为它们为空,因此可以继续为 Bob 的母亲调用 f()
  7. 现在我们在 combine() 中,第一个参数 — current — 是 Bob 的母亲。 combine() 函数实例的上下文来自 person 是 Bob 时进行的函数调用,而 Bob 绝对不是他自己的母亲。

关于javascript - Eloquent Javascript Book 第 5 章关于递归和祖先的示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37471924/

相关文章:

C 程序 : Print Linked List from Recursive Ordering Function

java - 迭代解决方案的递归

javascript - Vue拖放中的递归组件&递归嵌套

javascript - 无法更新 ng-repeat 离开动画的范围

javascript - 从查询中传递模态 ID,以便它可以在另一个查询中使用

java - 两种打印所有排列的方法-返回与通过“结果”列表

javascript - 无法从通过调用 asyncStorage 函数返回值的异步函数获取值

javascript - 如何从用户输入的日期获取工作日?

c++ - 递归文件搜索

algorithm - 树递归-打印给定数字的子序列