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



在阅读这本书时,我发现了这段关于总结祖先的代码。有几个板已经处理了这个问题的不同部分,但我遇到的问题是这个块:

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

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

因此,首先将起始人物传递到reduceAncestors()。它调用f()(即combine()的内部函数),结果是用父函数调用valueFor()。这反过来将导致母亲被传递到f()父亲传递到f()。回到对countAncestors()的原始调用的上下文中,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不为null,我们调用f()—即CCD_ 27—这需要经过鲍勃、母亲和父亲
  4. 然而,在调用f()之前,我们需要与母亲和父亲一起调用valueFor(),因为这些调用的结果需要传递给f()
  5. 因此valueFor()与母亲一起被调用。想要调用f(),并且将需要检查母亲和父亲(即Bob母亲的母亲和Bob母亲的父亲)
  6. 这两个祖父母的呼叫很快就失败了,因为它们为空,所以Bob母亲对f()的呼叫可以继续
  7. 现在我们进入combine(),第一个参数—current—是鲍勃的母亲。combine()函数实例的上下文来自于person是Bob时进行的函数调用,Bob肯定不是他自己的母亲

嗯,只有一种情况是current等于person。Wich是在longLivingPercentage(byName["Emile Haverbeke"])中通过的最初的人。其他时候,current是埃米尔·哈弗贝克的祖先。因为person是埃米尔·哈弗贝克,所以除了埃米尔·哈弗贝克之外,person一直都不是current

我认为这个代码(current!=person)的目的是从计数结果中去掉原来的那个人。在书中,作者没有添加current != person

最新更新