Iterator Helpersがそのうち使えるようになるらしいけど、現時点(2025.3)でvanilla JSでは使えない場合の方が多いので自前で薄ーいラッパーaddHelpers()を作ってみました。
中味がどうなってるか興味があったし、今は使えてない場所でもお手軽に使えるやつが欲しかったのです。
たぶんIterator.from()の車輪の再発明ってことです。
const addHelpers = iter => ({
next: () => iter.next(),
[Symbol.iterator]: () => iter,
map: f =>
addHelpers(
function* () {
let index = 0
for (const value of iter) {
yield f(value, index)
index++
}
}()
),
flatMap: f =>
addHelpers(
function* () {
let index = 0
for (const value of iter) {
yield* f(value, index)
index++
}
}()
),
filter: f =>
addHelpers(
function* () {
let index = 0
for (const value of iter) {
if (f(value, index)) yield value
index++
}
}()
),
drop: n =>
addHelpers(
function* () {
let index = 0
for (const value of iter) {
if (index >= n) yield value
index++
}
}()
),
take: n =>
addHelpers(
function* () {
let index = 0
for (const value of iter) {
if (index >= n) return
yield value
index++
}
}()
),
forEach: f => {
let index = 0
for (const value of iter) {
f(value, index)
index++
}
},
reduce: (f, init) => {
let acc = init
let index = 0
for (const value of iter) {
if (index === 0 && init === undefined) acc = value
else acc = f(acc, value, index)
index++
}
return acc
},
toArray: () => [...iter],
every: f => {
let index = 0
for (const value of iter) {
if (!f(value, index)) return false
index++
}
return true
},
some: f => {
let index = 0
for (const value of iter) {
if (f(value, index)) return true
index++
}
return false
},
find: f => {
let index = 0
for (const value of iter) {
if (f(value, index)) return value
index++
}
return undefined
},
})
使い方:
イテレーターオブジェクトに addHelpers を適用すると、ヘルパーメソッドが使えるイテレーターオブジェクトが帰ってきます。あとはお好みでメソッドチェーンすればよい。
以下は無限イテレーターをヘルパーメソッド使用可能にし、ある範囲を切り出してmapする例です。
const countG = n => function*(){
while(true) yield n++
}()
console.log(
addHelpers( countG(1) )
.drop(3)
.take(7)
.map( e => e * 2)
.toArray()
) // [ 8, 10, 12, 14, 16, 18, 20 ]
これで来たるべきその日のために色々試すことができます。
何か問題があればコメントよろしくお願いします。