Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
node-version: 20

- name: Make test directory
id: tmp-dir
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
22
17 changes: 1 addition & 16 deletions lib/es6/Stdlib_Iterator.js
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@



function forEach(iterator, f) {
let iteratorDone = false;
while (!iteratorDone) {
let match = iterator.next();
f(match.value);
iteratorDone = match.done;
};
}

export {
forEach,
}
/* No side effect */
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
15 changes: 1 addition & 14 deletions lib/js/Stdlib_Iterator.js
Original file line number Diff line number Diff line change
@@ -1,14 +1 @@
'use strict';


function forEach(iterator, f) {
let iteratorDone = false;
while (!iteratorDone) {
let match = iterator.next();
f(match.value);
iteratorDone = match.done;
};
}

exports.forEach = forEach;
/* No side effect */
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
6 changes: 6 additions & 0 deletions runtime/Stdlib_Array.res
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,9 @@ let findMap = (arr, f) => {
let last = a => a->get(a->length - 1)

external ignore: array<'a> => unit = "%ignore"

@send
external entries: array<'a> => Stdlib_Iterator.t<(int, 'a)> = "entries"

@send
external values: array<'a> => Stdlib_Iterator.t<'a> = "values"
34 changes: 34 additions & 0 deletions runtime/Stdlib_Array.resi
Original file line number Diff line number Diff line change
Expand Up @@ -1387,3 +1387,37 @@ let last: array<'a> => option<'a>
without having to store or process it further.
*/
external ignore: array<'a> => unit = "%ignore"

/**
`entries(array)` returns a new array iterator object that contains the key/value pairs for each index in the array.

See [Array.prototype.entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries) on MDN.

## Examples

```rescript
let array = [5, 6, 7]
let iterator : Iterator.t<(int, int)> = array->Array.entries
iterator->Iterator.next->assertEqual({done: false, value: Some((0, 5))})
iterator->Iterator.next->assertEqual({done: false, value: Some((1, 6))})
```
*/
@send
external entries: array<'a> => Stdlib_Iterator.t<(int, 'a)> = "entries"

/**
`values(array)` returns a new array iterator object that contains the values for each index in the array.

See [Array.prototype.values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values) on MDN.

## Examples

```rescript
let array = [5, 6, 7]
let iterator : Iterator.t<int> = array->Array.values
iterator->Iterator.next->assertEqual({done: false, value: Some(5)})
iterator->Iterator.next->assertEqual({done: false, value: Some(6)})
```
*/
@send
external values: array<'a> => Stdlib_Iterator.t<'a> = "values"
41 changes: 31 additions & 10 deletions runtime/Stdlib_Iterator.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,38 @@ type value<'a> = {
}

@send external next: t<'a> => value<'a> = "next"
external toArray: t<'a> => array<'a> = "Array.from"
@send
external toArray: t<'a> => array<'a> = "toArray"
external toArrayWithMapper: (t<'a>, 'a => 'b) => array<'b> = "Array.from"

let forEach = (iterator, f) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm for this change 👍

Iterator.forEach's behaviour was different to Iterator.prototype.forEach as the latter only calls its callback with yielded values, not the iterator's final return value.

let iteratorDone = ref(false)

while !iteratorDone.contents {
let {done, value} = iterator->next
f(value)
iteratorDone := done
}
}
@send
external forEach: (t<'a>, 'a => unit) => unit = "forEach"

external ignore: t<'a> => unit = "%ignore"

@send
external drop: (t<'a>, int) => t<'a> = "drop"

@send
external every: (t<'a>, 'a => bool) => bool = "every"

@send
external filter: (t<'a>, 'a => bool) => t<'a> = "filter"

@send
external find: (t<'a>, 'a => bool) => option<'a> = "find"

@send
external flatMap: (t<'a>, 'a => t<'b>) => t<'b> = "flatMap"

@send
external map: (t<'a>, 'a => 'b) => t<'b> = "map"

@send
external reduce: (t<'a>, ('acc, 'a) => 'acc, ~initialValue: 'acc=?) => 'acc = "reduce"

@send
external some: (t<'a>, 'a => bool) => bool = "some"

@send
external take: (t<'a>, int) => t<'a> = "take"
189 changes: 168 additions & 21 deletions runtime/Stdlib_Iterator.resi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/***
Bindings to JavaScript iterators.

See [`iterator protocols`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
See [`Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) on MDN.
*/

/**
Expand Down Expand Up @@ -50,7 +50,7 @@ external next: t<'a> => value<'a> = "next"
Turns an iterator into an array of the remaining values.
Remember that each invocation of `next` of an iterator consumes a value. `Iterator.toArray` will consume all remaining values of the iterator and return them in an array to you.

See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
See [Iterator.prototype.toArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray) on MDN.

## Examples
```rescript
Expand All @@ -61,16 +61,17 @@ map->Map.set("someKey2", "someValue2")
// `Map.keys` returns all keys of the map as an iterator.
let mapKeysAsArray = map->Map.keys->Iterator.toArray

Console.log(mapKeysAsArray) // Logs ["someKey", "someKey2"] to the console.
mapKeysAsArray->assertEqual(["someKey", "someKey2"])
```
*/
external toArray: t<'a> => array<'a> = "Array.from"
@send
external toArray: t<'a> => array<'a> = "toArray"

/**
`toArray(iterator)` turns `iterator` into an array of its remaining values, applying the provided mapper function on each item.
Remember that each invocation of `next` of an iterator consumes a value. `Iterator.toArrayWithMapper` will consume all remaining values of the iterator and return them in an array to you.

See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
See [Iterator.prototype.toArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray) on MDN.

## Examples
```rescript
Expand All @@ -83,7 +84,7 @@ let mapKeysAsArray = map
->Map.keys
->Iterator.toArrayWithMapper(key => key->String.length)

Console.log(mapKeysAsArray) // Logs [7, 8] to the console.
mapKeysAsArray->assertEqual([7, 8])
```
*/
external toArrayWithMapper: (t<'a>, 'a => 'b) => array<'b> = "Array.from"
Expand All @@ -95,25 +96,17 @@ See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript

## Examples
```rescript
let iterator: Iterator.t<string> = %raw(`
(() => {
var array1 = ['a', 'b', 'c'];
var iterator1 = array1[Symbol.iterator]();
return iterator1
})()
`)
let iterator: Iterator.t<string> = ["a", "b", "c"]->Array.values
let acc = ref("")
iterator->Iterator.forEach(v => {
switch v {
| Some("a" | "b" | "c") => assert(true)
| other =>
other
->Option.isNone
->assertEqual(true)
}
acc := acc.contents ++ v
})

acc.contents->assertEqual("abc")
```
*/
let forEach: (t<'a>, option<'a> => unit) => unit
@send
external forEach: (t<'a>, 'a => unit) => unit = "forEach"

/**
`ignore(iterator)` ignores the provided iterator and returns unit.
Expand All @@ -122,3 +115,157 @@ let forEach: (t<'a>, option<'a> => unit) => unit
without having to store or process it further.
*/
external ignore: t<'a> => unit = "%ignore"

/**
`drop((iterator, n))` returns a new iterator helper object that skips the given number of elements at the start of this iterator.

See [Iterator.prototype.drop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/drop) on MDN.

## Examples
```rescript
let fibonacci: Iterator.t<int> = [ 1, 1, 2, 3, 5, 8, 13, 21 ]->Array.values

let seq = fibonacci->Iterator.drop(2)
seq->Iterator.next->assertEqual({done: false, value: Some(2)})
seq->Iterator.next->assertEqual({done: false, value: Some(3)})
```
*/
@send
external drop: (t<'a>, int) => t<'a> = "drop"

/**
`every(iterator, fn)` tests whether all elements in the iterator pass the test implemented by the provided function.

See [Iterator.prototype.every](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/every) on MDN.

## Examples
```rescript
let fibonacci: Iterator.t<int> = [ 1, 1, 2, 3, 5, 8, 13, 21 ]->Array.values

let areAllEven = fibonacci->Iterator.every(n => n % 2 == 0)
areAllEven->assertEqual(false)
```
*/
@send
external every: (t<'a>, 'a => bool) => bool = "every"

/**
`filter(iterator, fn)` returns a new iterator helper object that contains the elements of the original iterator that pass the test implemented by the provided function.

See [Iterator.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/filter) on MDN.

## Examples
```rescript
let fibonacci: Iterator.t<int> = [ 1, 1, 2, 3, 5, 8, 13, 21 ]->Array.values

let seq = fibonacci->Iterator.filter(n => n % 2 == 0)
seq->Iterator.next->assertEqual({done: false, value: Some(2)})
seq->Iterator.next->assertEqual({done: false, value: Some(8)})
```
*/
@send
external filter: (t<'a>, 'a => bool) => t<'a> = "filter"

/**
`find(iterator, fn)` returns the value of the first element in the iterator that satisfies the provided testing function.

See [Iterator.prototype.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/find) on MDN.

## Examples
```rescript
let fibonacci: Iterator.t<int> = [ 1, 1, 2, 3, 5, 8, 13, 21 ]->Array.values

let seq = fibonacci->Iterator.find(n => n % 2 == 0)
seq->assertEqual(Some(2))
```
*/
@send
external find: (t<'a>, 'a => bool) => option<'a> = "find"

/**
`flatMap(iterator, fn)` returns a new iterator helper object that contains the elements of the original iterator that pass the test implemented by the provided function.

See [Iterator.prototype.flatMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/flatMap) on MDN.

## Examples
```rescript
let map1 = Map.fromArray([("a", 1), ("b", 2), ("c", 3)])
let map2 = Map.fromArray([("d", 4), ("e", 5), ("f", 6)])

let letters =
[map1, map2]
->Array.values
->Iterator.flatMap(m => Map.keys(m))
->Array.fromIterator
letters->assertEqual(["a", "b", "c", "d", "e", "f"])
```
*/
@send
external flatMap: (t<'a>, 'a => t<'b>) => t<'b> = "flatMap"

/**
`map(iterator, fn)` returns a new iterator helper object that yields elements of the iterator, each transformed by a mapping function.

See [Iterator.prototype.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/map) on MDN.

## Examples
```rescript
let map = Map.fromArray([("a", 1), ("b", 2), ("c", 3)])
let letters = map->Map.keys->Iterator.map(v => v->String.toUpperCase)->Array.fromIterator
letters->assertEqual(["A", "B", "C"])
```
*/
@send
external map: (t<'a>, 'a => 'b) => t<'b> = "map"

/**
`reduce(iterator, fn, initialValue)` applies a function against an accumulator and each element in the iterator (from left to right) to reduce it to a single value.

See [Iterator.prototype.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/reduce) on MDN.

## Examples
```rescript
let numbers: Iterator.t<int> = [ 1, 2, 3 ]->Array.values

let sum = numbers->Iterator.reduce((acc, n) => acc + n, ~initialValue=0)
sum->assertEqual(6)
```
*/
@send
external reduce: (t<'a>, ('acc, 'a) => 'acc, ~initialValue: 'acc=?) => 'acc = "reduce"

/**
`some(iterator, fn)` The some() method of Iterator instances is similar to Array.some:
it tests whether at least one element produced by the iterator passes the test implemented by the provided function.
It returns a boolean value.

See [Iterator.prototype.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/some) on MDN.

## Examples
```rescript
let numbers: Iterator.t<int> = [ 1, 2, 3 ]->Array.values

let hasEven = numbers->Iterator.some(n => n % 2 == 0)
hasEven->assertEqual(true)
```
*/
@send
external some: (t<'a>, 'a => bool) => bool = "some"

/**
`take((iterator, n))` returns a new iterator helper object that contains the first `n` elements of this iterator.

See [Iterator.prototype.take](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/take) on MDN.

## Examples
```rescript
let fibonacci: Iterator.t<int> = [ 1, 1, 2, 3, 5, 8, 13, 21 ]->Array.values

let seq = fibonacci->Iterator.take(2)
seq->Iterator.next->assertEqual({done: false, value: Some(1)})
seq->Iterator.next->assertEqual({done: false, value: Some(1)})
seq->Iterator.next->assertEqual({done: true, value: None})
```
*/
@send
external take: (t<'a>, int) => t<'a> = "take"
Loading
Loading