在阅读这本书时,我发现了这段关于总结祖先的代码。有几个板已经处理了这个问题的不同部分,但我遇到的问题是这个块:
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
仍然是原始人,但current
到combine()
的传入值将不同(它将是母亲或父亲、外祖母/祖父或外祖母/外祖父等)。
让我们看看longLivingPercentage()
函数中对countAncestors()
的第一次调用。我们传入起始人物和始终返回true
的伪test()
。我不知道代码期望家谱数据结构是什么,但让我们假设它是这样的:
{
person: "Bob",
mother: {
person: "Mary",
mother: null,
father: null
},
father: {
person: "Jim",
mother: null,
father: null
}
}
因此:
- 为Bob调用
countAncestors()
函数 - 这会将Bob传递给
reduceAncestors()
,以及对该combine()
函数的引用 - 在
reduceAncestors()
中,为Bob调用valueFor()
,由于Bob不为null,我们调用f()
—即CCD_ 27—这需要经过鲍勃、母亲和父亲 - 然而,在调用
f()
之前,我们需要与母亲和父亲一起调用valueFor()
,因为这些调用的结果需要传递给f()
- 因此
valueFor()
与母亲一起被调用。也想要调用f()
,并且还将需要检查母亲和父亲(即Bob母亲的母亲和Bob母亲的父亲) - 这两个祖父母的呼叫很快就失败了,因为它们为空,所以Bob母亲对
f()
的呼叫可以继续 - 现在我们进入
combine()
,第一个参数—current
—是鲍勃的母亲。combine()
函数实例的上下文来自于person
是Bob时进行的函数调用,Bob肯定不是他自己的母亲
嗯,只有一种情况是current
等于person
。Wich是在longLivingPercentage(byName["Emile Haverbeke"])
中通过的最初的人。其他时候,current
是埃米尔·哈弗贝克的祖先。因为person
是埃米尔·哈弗贝克,所以除了埃米尔·哈弗贝克之外,person
一直都不是current
我认为这个代码(current!=person)的目的是从计数结果中去掉原来的那个人。在书中,作者没有添加current != person
。