dam*_*amd 11 javascript functional-programming generator
我有一个generateNumbers用JavaScript 调用的生成器和另一个生成器generateLargerNumbers,它生成每个生成的值并向其generateNumbers应用一个函数addOne,如下所示:
function addOne(value) {
return value + 1
}
function* generateNumbers() {
yield 1
yield 2
yield 3
}
function* generateLargerNumbers() {
for (const number of generateNumbers()) {
yield addOne(number)
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有从生成的值中构建数组,是否有任何更简单的方法可以做到这一点?我想的是:
function* generateLargerNumbers() {
yield* generateNumbers().map(addOne) // obviously doesn't work
}
Run Code Online (Sandbox Code Playgroud)
高阶发生器
您可以选择自己操纵生成器功能
const Generator =
{
map: (f,g) => function* (...args)
{
for (const x of g (...args))
yield f (x)
},
filter: (f,g) => function* (...args)
{
for (const x of g (...args))
if (f (x))
yield x
}
}
// some functions !
const square = x =>
x * x
const isEven = x =>
(x & 1) === 0
// a generator !
const range = function* (x = 0, y = 1)
{
while (x < y)
yield x++
}
// higher order generator !
for (const x of Generator.map (square, Generator.filter (isEven, range)) (0,10))
console.log('evens squared', x)Run Code Online (Sandbox Code Playgroud)
高阶迭代器
或者,您可以选择操纵迭代器
const Iterator =
{
map: (f, it) => function* ()
{
for (const x of it)
yield f (x)
} (),
filter: (f, it) => function* ()
{
for (const x of it)
if (f (x))
yield x
} ()
}
// some functions !
const square = x =>
x * x
const isEven = x =>
(x & 1) === 0
// a generator !
const range = function* (x = 0, y = 1)
{
while (x < y)
yield x++
}
// higher-order iterators !
for (const x of Iterator.map (square, Iterator.filter (isEven, range (0, 10))))
console.log('evens squared', x)Run Code Online (Sandbox Code Playgroud)
建议
在大多数情况下,我认为操作迭代器更为实用,因为它具有定义良好的接口(尽管很笨拙)。它允许您做类似的事情
Iterator.map (square, Iterator.filter (isEven, [10,11,12,13]))
Run Code Online (Sandbox Code Playgroud)
而另一种方法是
Generator.map (square, Generator.filter (isEven, Array.from)) ([10,11,12,13])
Run Code Online (Sandbox Code Playgroud)
两者都有用例,但我发现前者比后者好得多
持久迭代器
JavaScript的有状态迭代器使我很烦恼–随后的每次调用都将.next不可逆地更改内部状态。
但!没有什么可以阻止您创建自己的迭代器,然后创建适配器以插入JavaScript的堆栈安全生成器机制
如果您对此感兴趣,那么您可能会喜欢在这里找到的一些其他附带示例:循环到我的对象中的文件系统结构以获取所有文件
唯一的收获不是我们可以重用持久性迭代器,而是通过这种实现,由于具有备忘录功能,后续读取甚至比第一次读取还要快 –得分:JavaScript 0,持久性迭代器2
Iterator.map (square, Iterator.filter (isEven, [10,11,12,13]))
Run Code Online (Sandbox Code Playgroud)
没有内置的映射Generator对象的方法,但是您可以滚动自己的函数:
const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.map = function* (mapper, thisArg) {
for (const val of this) {
yield mapper.call(thisArg, val);
}
};
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
function generateLargerNumbers() {
return generateNumbers().map(addOne);
}
Run Code Online (Sandbox Code Playgroud)
const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.map = function* (mapper, thisArg) {
for (const val of this) {
yield mapper.call(thisArg, val);
}
};
Run Code Online (Sandbox Code Playgroud)