Eloquent Javascript Book第5章关于递归和祖先的例子

时间:2016-05-26 22:14:19

标签: javascript recursion

当我看到关于总结祖先的这段代码时,仔细阅读这本书的雄辩javascript。有几个板已经完成了不同的部分,但我遇到麻烦的部分是这个块:

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

具体来说,什么时候当前没有==对人?我似乎无法找到一种情况,因为现在总是被称为人。但显然我错过了一些东西,因为当我拿出那些代码时,它会返回一个不同的解决方案。以下是代码。

 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"]));

2 个答案:

答案 0 :(得分:3)

请注意,valueFor()中的reduceAncestors()函数是与原始人的父母一起递归调用的,然后是祖父母等。这些递归调用可以调用f(),并且f()是来自combine()的{​​{1}}函数。

因此,首先将起始人传递给countAncestors()。这会调用reduceAncestors()(这是f()内部函数)与父母调用combine()的结果。反过来,这将导致母亲传递给valueFor(),而父亲传递给f()。回到原始调用f()的上下文中,countAncestors()仍是原始人,但person的传入值为current将是不同的(它将是母亲或父亲或外祖母/祖父或祖母/祖父等)。

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

true

因此:

  1. 为Bob调用{ person: "Bob", mother: { person: "Mary", mother: null, father: null }, father: { person: "Jim", mother: null, father: null } } 函数。
  2. 将Bob传递给countAncestors(),以及对该reduceAncestors()函数的引用。
  3. combine()中,为Bob调用reduceAncestors(),由于Bob不为空,我们接到valueFor()的调用 - 这是f() - 需要通过鲍勃,母亲和父亲。
  4. 然而,在调用combine()之前,我们需要与母亲和父亲调用f(),因为这些调用的结果需要传递给{ {1}}。
  5. 所以与母亲一起召唤valueFor()。那个想要打电话给f(),而需要检查母亲和父亲(也就是Bob的母亲的母亲和Bob的母亲的父亲)。 / LI>
  6. 这两个祖父母的呼叫失败很快,因为它们是空的,因此可以继续拨打valueFor()给鲍勃的母亲。
  7. 现在我们在f(),第一个参数 - f() - 是Bob的母亲。 combine()函数实例的上下文来自于current是鲍勃时所做的函数调用,鲍勃绝对不是他自己的母亲。

答案 1 :(得分:0)

好吧,只有一种情况,current等于person。 Wich是通过longLivingPercentage(byName["Emile Haverbeke"])的原始人。在其他时间,current是Emile Haverbeke的祖先。由于person是Emile Haverbeke,所以person一直不是current,除了Emile Haverbeke。

我认为此代码(当前的!=人员)的目的是从计数结果中摆脱原始人员。在书中,作者未添加current != person