0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[JavaScript] vanilla JSで Iterator Helpers が試せるラッパーを作ってみた

Last updated at Posted at 2025-03-23

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 ]

これで来たるべきその日のために色々試すことができます。

何か問題があればコメントよろしくお願いします。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?