Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
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. */
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"@types/node": "^20.14.9",
"@types/semver": "^7.7.0",
"@yarnpkg/types": "^4.0.1",
"es-iterator-helpers": "1.2.1",
"mocha": "10.8.2",
"nyc": "15.0.0",
"semver": "^7.7.2",
Expand Down
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<'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> = array->Array.entries
Console.log(iterator->Iterator.next) // {done: false, value: [0,5]}
Console.log(iterator->Iterator.next) // {done: false, value: [1,6]}
```
*/
@send
external entries: array<'a> => Stdlib_Iterator.t<'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
Console.log(iterator->Iterator.next) // {done: false, value: 5}
Console.log(iterator->Iterator.next) // {done: false, value: 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"
186 changes: 167 additions & 19 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 @@ -64,13 +64,14 @@ let mapKeysAsArray = map->Map.keys->Iterator.toArray
Console.log(mapKeysAsArray) // Logs ["someKey", "someKey2"] to the console.
```
*/
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 @@ -95,25 +96,18 @@ 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
iterator->Iterator.forEach(v => {
switch v {
| Some("a" | "b" | "c") => assert(true)
| other =>
other
->Option.isNone
->assertEqual(true)
}
Console.log(v)
})

// "a"
// "b"
// "c"
```
*/
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 +116,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.entries

let seq = fibonacci->Iterator.drop(2)
Console.log(seq->Iterator.next) // {done: false, value: Some(2)}
Console.log(seq->Iterator.next) // {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.entries

let areAllEven = fibonacci->Iterator.every(n => n % 2 == 0)
Console.log(areAllEven) // 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.entries

let seq = fibonacci->Iterator.filter(n => n % 2 == 0)
Console.log(seq->Iterator.next) // {done: false, value: Some(2)}
Console.log(seq->Iterator.next) // {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.entries

let seq = fibonacci->Iterator.find(n => n % 2 == 0)
Console.log(seq) // 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
Console.log(letters) // ["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
Console.log(letters) // ["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.entries

let sum = numbers->Iterator.reduce((acc, n) => acc + n, ~initialValue=0)
Console.log(sum) // 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)
Console.log(hasEven) // 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)
Console.log(seq->Iterator.next) // {done: false, value: Some(1)}
Console.log(seq->Iterator.next) // {done: false, value: Some(1)}
Console.log(seq->Iterator.next) // {done: true, value: None}
```
*/
@send
external take: (t<'a>, int) => t<'a> = "take"
12 changes: 12 additions & 0 deletions tests/analysis_tests/tests/src/expected/Completion.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ Path Array.
"tags": [],
"detail": "(array<'a>, int) => 'a",
"documentation": {"kind": "markdown", "value": "\n`getUnsafe(array, index)` returns the element at `index` of `array`.\n\nThis is _unsafe_, meaning it will return `undefined` value if `index` does not exist in `array`.\n\nUse `Array.getUnsafe` only when you are sure the `index` exists (i.e. when using for-loop).\n\n## Examples\n```rescript\nlet array = [1, 2, 3]\nfor index in 0 to array->Array.length - 1 {\n let value = array->Array.getUnsafe(index)\n Console.log(value)\n}\n```\n"}
}, {
"label": "entries",
"kind": 12,
"tags": [],
"detail": "array<'a> => Iterator.t<'a>",
"documentation": {"kind": "markdown", "value": "\n`entries(array)` returns a new array iterator object that contains the key/value pairs for each index in the array.\n\nSee [Array.prototype.entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries) on MDN.\n\n## Examples\n\n```rescript\nlet array = [5, 6, 7]\nlet iterator : Iterator.t<int> = array->Array.entries\nConsole.log(iterator->Iterator.next) // {done: false, value: [0,5]}\nConsole.log(iterator->Iterator.next) // {done: false, value: [1,6]}\n```\n"}
}, {
"label": "unshiftMany",
"kind": 12,
Expand Down Expand Up @@ -376,6 +382,12 @@ Path Array.
"tags": [],
"detail": "'a => bool",
"documentation": null
}, {
"label": "values",
"kind": 12,
"tags": [],
"detail": "array<'a> => Iterator.t<'a>",
"documentation": {"kind": "markdown", "value": "\n`values(array)` returns a new array iterator object that contains the values for each index in the array.\n\nSee [Array.prototype.values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values) on MDN.\n\n## Examples\n\n```rescript\nlet array = [5, 6, 7]\nlet iterator : Iterator.t<int> = array->Array.values\nConsole.log(iterator->Iterator.next) // {done: false, value: 5}\nConsole.log(iterator->Iterator.next) // {done: false, value: 6}\n```\n "}
}, {
"label": "indexOfOpt",
"kind": 12,
Expand Down
Loading