使用ES6的generator实现可变的无限集合
无限且惰加载的集合是许多语言的特性,现在可以使用ES6的新iterator和generator实现了。通常我们使用数组Array在内存中建立有限大小的集合,如果是无限大则可能会消耗大量内存,那么为什么需要无限的集合?因为很多时候我们无法事先确定集合的大小,只能假设这个集合是可变的无限大了。
Iterator
允许构建无限集合,内建语言的构造器用来遍历这个无限集合,也就是可以使用for-of循环遍历,为了构造一个Iterable,你需要返回一个key为Symbol.iterator的iterator 实例,这个iterator方法中只需要一个next()方法,用来返回一个结果对象,其中包含done和值,前者表示是否有更多元素,后者就是包含真正的元素值,代码如下:
var naturalNums = {
[Symbol.iterator]: (()=>{
let i = 0;
return {
next: () => {
return {done: false, value: i++};
}
}
})
};
上述无限大的集合构建后,你可以使用for-of循环遍历:
for(let i of naturalNums){
if(i > 10) break; // 千万别忘记中断,否则一直无限循环下去
console.log(i);
}
Generator
Generator是基于iterator的语法糖,可以节省很多繁琐的代码,让你集中业务逻辑,代码如下:
var naturalNums = function* (){
let i = 0;
while(true){
yield i++;
}
}
这个代码比前面iterator简洁,使用方法是一样:
for(let i of naturalNums()){ //这里函数名称与前面调用不同
if(i > 10) break;
console.log(i);
}
Gentoo库包 - Generator工具
虽然generator可以方便构建一个无限大且懒惰加载的集合,但是无法使用流处理如filter map 和reduce等方法,而Gentoo工具则可以提供类似方法,比如前面案例如下:
const sum =
gentoo.chain(gentoo.range(1, Number.POSITIVE_INFINITY))
.filter(isPrime)
.limit(100)
.reduce((memo, val) => memo + val, 0)
.value()