rescript-core icon indicating copy to clipboard operation
rescript-core copied to clipboard

Iterator.toArray does not work with iterators.

Open samwightt opened this issue 1 year ago • 2 comments

According to MDN, an iterator is any object that implements a next method that returns an IteratorResult (Iterator.value<'a> in RescriptCore). An iterable is any object that implements the [Symbol.iterator] method that returns an iterator.

Right now Iterator.toArray is defined as an extern using Array.from:

https://github.com/rescript-association/rescript-core/blob/22642eafb6c268c8348bd68c8569a30918b66d6b/src/Core__Iterator.res#L9C1-L9C52

However, Array.from accepts an iterable, not an iterator. This means that if we implement a valid iterator (not an iterable, but an object with next), Iterator.next and Iterator.forEach will work just fine but Iterator.toArray will not: it returns an empty array.

To fix this, Iterator.toArray should be defined something like:

let toArray = (iterator: t<'a>): array<'a> => {
  let results = []
  iterator->forEach(value => {
    switch value {
    | Some(value) => Array.push(results, value)
    | None => _
    }
  })
  results
}

To use Array.from, a separate module for iterables should be defined and used instead.

samwightt avatar Aug 19 '24 19:08 samwightt

good catch @samwightt! We'll look into it before v12.

tsnobip avatar Mar 07 '25 10:03 tsnobip

MDN states that

The Iterator class provides a [Symbol.iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/Symbol.iterator) method that returns the iterator object itself, making the iterator also iterable.

@samwightt Do you have any counter-example of iterators that do not work with Array.from?

tsnobip avatar Mar 13 '25 09:03 tsnobip