Skip to content

[Proposal] Add Iterator.forEach and AsyncIterator.forEach #38

Closed
@zth

Description

@zth

The idiomatic way of iterating through all entries of an (async) iterator in JS is to use the for const of syntax:

// For regular iterators
for (const item of iterator) {
  console.log(item)
}

// For async iterators
for await (const item of iterator) {
  console.log(item)
}

However, this isn't possible in ReScript because we have no for const of syntax. So, I propose we add 2 helpers that accomplishes the same thing as for const of does, namely iterating through all items from the iterator.

They'd look like this:

// Regular iterator
// forEach: (Iterator.t<'a>, option<'a> => unit) => unit
someIterator->Iterator.forEach(value => {
  Console.log(value) // `option<'a>`
})

// Async iterator. Returns a promise since it's async
// forEach: (Iterator.t<'a>, option<'a> => unit) => promise<unit>
let processAsyncIterator = async () => {
 await someAsyncIterator->AsyncIterator.forEach(value => {
    Console.log(value) // `option<'a>`
  })
}

The implementation would be via a while loop:

// Regular
let forEach = (iterator, f) => {
  let iteratorDone = ref(false)

  while !iteratorDone.contents {
    let {done, value} = iterator->Iterator.next
    f(value)
    iteratorDone := done
  }
}

// Async
let forEach = async (iterator, f) => {
  let iteratorDone = ref(false)

  while !iteratorDone.contents {
    let {done, value} = await iterator->AsyncIterator.next
    f(value)
    iteratorDone := done
  }
}

I think this fits in Core because we'll never have the for const of syntax in ReScript, and this would help make it easy for beginners to use iterators whenever they encounter them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalProposals for changes to Core.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions