为什么这个生成器函数包装器在每次函数调用时创建一个新的生成器时使用迭代器?
Why is this generator function wrapper consuming the iterator when I create a new generator each function call?
当直接从新制作的序列中减少时,我可以多次减少同一个序列,但是如果我尝试重复减少从 .map 创建的序列,它只在第一次有效吗?
我似乎正在使用原始迭代器...但我没有看到 how/where。据我理解这段代码,Sequence::map 构建了一个新的生成器,每次调用它时都会迭代,所以它应该能够每次都重复使用相同的 seq。有人可以帮助我了解我所缺少的吗?
// A wrapper for a generatorFn
class Sequence {
constructor(generatorFn) {
if (typeof generatorFn === "function") {
this[Symbol.iterator] = generatorFn;
} else {
throw new Error("Cannot create Sequence from provided argument");
}
}
static of(obj) {
//Create a generatorFn from an iterable object
function* genFn() {
for (const x of obj) {
yield x;
}
}
return new Sequence(genFn);
}
map(fn) {
//Make a generator from the generator function
const gen = this[Symbol.iterator]();
//Make a new generator function that applies fn to each value
function* mapGenFn() {
for (const x of gen) {
yield fn(x);
}
}
// Create a new sequence using the new generator function
return new Sequence(mapGenFn);
}
reduce(fn, initial) {
let acc;
let first = true;
// Make a new generator from the seq's generator fn
const gen = this[Symbol.iterator]();
if (initial) {
acc = initial
// iterate on the new generator
for (const x of gen) {
acc = fn(acc, x);
}
} else {
acc = this.fold(fn);
}
return acc;
}
fold(fn) {
const gen = this[Symbol.iterator]();
let first = true;
let acc;
for (const x of gen) {
if (first) {
acc = x;
first = false;
} else {
acc = fn(acc, x);
}
}
return acc;
}
}
const seqA = Sequence.of([1,2,3])
console.log("SeqA1 is: ", seqA.reduce((acc, x) => acc + x)); // 6
console.log("SeqA2 is: ", seqA.reduce((acc, x) => acc + x)); // 6
console.log("SeqA3 is: ", seqA.reduce((acc, x) => acc + x)); // 6
const seqB = Sequence.of([1,2,3]).map(x => x + 1);
console.log("SeqB1 is: ", seqB.reduce((acc, x) => acc + x)); // 9
console.log("SeqB2 is: ", seqB.reduce((acc, x) => acc + x)); // undefined
console.log("SeqB3 is: ", seqB.reduce((acc, x) => acc + x)); // undefined
A fiddle 演示问题:https://jsfiddle.net/qsh9mupz/5/
const gen = this[Symbol.iterator]()
不是 每次使用新序列时都创建,而是在调用 .map(…)
时只创建一次。将该部分移动到 mapGenFn
:
map(fn) {
const gen = this[Symbol.iterator]; // no call here!
return new Sequence(function* mapGenFn() {
for (const x of gen()) {
// ^^ create new iterator here every time the sequence uses mapGenFn
yield fn(x);
}
});
}
当直接从新制作的序列中减少时,我可以多次减少同一个序列,但是如果我尝试重复减少从 .map 创建的序列,它只在第一次有效吗?
我似乎正在使用原始迭代器...但我没有看到 how/where。据我理解这段代码,Sequence::map 构建了一个新的生成器,每次调用它时都会迭代,所以它应该能够每次都重复使用相同的 seq。有人可以帮助我了解我所缺少的吗?
// A wrapper for a generatorFn
class Sequence {
constructor(generatorFn) {
if (typeof generatorFn === "function") {
this[Symbol.iterator] = generatorFn;
} else {
throw new Error("Cannot create Sequence from provided argument");
}
}
static of(obj) {
//Create a generatorFn from an iterable object
function* genFn() {
for (const x of obj) {
yield x;
}
}
return new Sequence(genFn);
}
map(fn) {
//Make a generator from the generator function
const gen = this[Symbol.iterator]();
//Make a new generator function that applies fn to each value
function* mapGenFn() {
for (const x of gen) {
yield fn(x);
}
}
// Create a new sequence using the new generator function
return new Sequence(mapGenFn);
}
reduce(fn, initial) {
let acc;
let first = true;
// Make a new generator from the seq's generator fn
const gen = this[Symbol.iterator]();
if (initial) {
acc = initial
// iterate on the new generator
for (const x of gen) {
acc = fn(acc, x);
}
} else {
acc = this.fold(fn);
}
return acc;
}
fold(fn) {
const gen = this[Symbol.iterator]();
let first = true;
let acc;
for (const x of gen) {
if (first) {
acc = x;
first = false;
} else {
acc = fn(acc, x);
}
}
return acc;
}
}
const seqA = Sequence.of([1,2,3])
console.log("SeqA1 is: ", seqA.reduce((acc, x) => acc + x)); // 6
console.log("SeqA2 is: ", seqA.reduce((acc, x) => acc + x)); // 6
console.log("SeqA3 is: ", seqA.reduce((acc, x) => acc + x)); // 6
const seqB = Sequence.of([1,2,3]).map(x => x + 1);
console.log("SeqB1 is: ", seqB.reduce((acc, x) => acc + x)); // 9
console.log("SeqB2 is: ", seqB.reduce((acc, x) => acc + x)); // undefined
console.log("SeqB3 is: ", seqB.reduce((acc, x) => acc + x)); // undefined
A fiddle 演示问题:https://jsfiddle.net/qsh9mupz/5/
const gen = this[Symbol.iterator]()
不是 每次使用新序列时都创建,而是在调用 .map(…)
时只创建一次。将该部分移动到 mapGenFn
:
map(fn) {
const gen = this[Symbol.iterator]; // no call here!
return new Sequence(function* mapGenFn() {
for (const x of gen()) {
// ^^ create new iterator here every time the sequence uses mapGenFn
yield fn(x);
}
});
}