Skip to content

Add a few Stdlib helpers #7516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#### :rocket: New Feature

- Add new Stdlib helpers: `String.capitalize`, `String.isEmpty`, `Dict.size`, `Dict.isEmpty`, `Array.isEmpty`, `Map.isEmpty`, `Set.isEmpty`. https://github.com/rescript-lang/rescript/pull/7516

#### :bug: Bug fix

- Fix formatting of nested records in `.resi` files. https://github.com/rescript-lang/rescript/pull/7741
Expand Down
5 changes: 5 additions & 0 deletions lib/es6/Stdlib_Array.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ function fromInitializer(length, f) {
return arr;
}

function isEmpty(arr) {
return arr.length === 0;
}

function equal(a, b, eq) {
let len = a.length;
if (len === b.length) {
Expand Down Expand Up @@ -183,6 +187,7 @@ export {
fromInitializer,
equal,
compare,
isEmpty,
indexOfOpt,
lastIndexOfOpt,
reduce,
Expand Down
46 changes: 33 additions & 13 deletions lib/es6/Stdlib_Dict.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,45 @@ function $$delete$1(dict, string) {
delete(dict[string]);
}

function forEach(dict, f) {
Object.values(dict).forEach(value => f(value));
}
let forEach = ((dict, f) => {
for (var i in dict) {
f(dict[i]);
}
});

function forEachWithKey(dict, f) {
Object.keys(dict).forEach(key => f(dict[key], key));
}
let forEachWithKey = ((dict, f) => {
for (var i in dict) {
f(dict[i], i);
}
});

function mapValues(dict, f) {
let target = {};
Object.keys(dict).forEach(key => {
let value = dict[key];
target[key] = f(value);
});
let mapValues = ((dict, f) => {
var target = {}, i;
for (i in dict) {
target[i] = f(dict[i]);
}
return target;
}
});

let size = ((dict) => {
var size = 0, i;
for (i in dict) {
size++;
}
return size;
});

let isEmpty = ((dict) => {
for (var _ in dict) {
return false
}
return true
});

export {
$$delete$1 as $$delete,
size,
isEmpty,
forEach,
forEachWithKey,
mapValues,
Expand Down
12 changes: 11 additions & 1 deletion lib/es6/Stdlib_Map.js
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */



function isEmpty(map) {
return map.size === 0;
}

export {
isEmpty,
}
/* No side effect */
12 changes: 11 additions & 1 deletion lib/es6/Stdlib_Set.js
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */



function isEmpty(set) {
return set.size === 0;
}

export {
isEmpty,
}
/* No side effect */
14 changes: 14 additions & 0 deletions lib/es6/Stdlib_String.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,23 @@ function searchOpt(s, re) {

}

function isEmpty(s) {
return s.length === 0;
}

function capitalize(s) {
if (s.length === 0) {
return s;
} else {
return s[0].toUpperCase() + s.slice(1);
}
}

export {
indexOfOpt,
lastIndexOfOpt,
searchOpt,
isEmpty,
capitalize,
}
/* No side effect */
5 changes: 5 additions & 0 deletions lib/js/Stdlib_Array.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ function fromInitializer(length, f) {
return arr;
}

function isEmpty(arr) {
return arr.length === 0;
}

function equal(a, b, eq) {
let len = a.length;
if (len === b.length) {
Expand Down Expand Up @@ -182,6 +186,7 @@ exports.make = make;
exports.fromInitializer = fromInitializer;
exports.equal = equal;
exports.compare = compare;
exports.isEmpty = isEmpty;
exports.indexOfOpt = indexOfOpt;
exports.lastIndexOfOpt = lastIndexOfOpt;
exports.reduce = reduce;
Expand Down
46 changes: 33 additions & 13 deletions lib/js/Stdlib_Dict.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,44 @@ function $$delete$1(dict, string) {
delete(dict[string]);
}

function forEach(dict, f) {
Object.values(dict).forEach(value => f(value));
}
let forEach = ((dict, f) => {
for (var i in dict) {
f(dict[i]);
}
});

function forEachWithKey(dict, f) {
Object.keys(dict).forEach(key => f(dict[key], key));
}
let forEachWithKey = ((dict, f) => {
for (var i in dict) {
f(dict[i], i);
}
});

function mapValues(dict, f) {
let target = {};
Object.keys(dict).forEach(key => {
let value = dict[key];
target[key] = f(value);
});
let mapValues = ((dict, f) => {
var target = {}, i;
for (i in dict) {
target[i] = f(dict[i]);
}
return target;
}
});

let size = ((dict) => {
var size = 0, i;
for (i in dict) {
size++;
}
return size;
});

let isEmpty = ((dict) => {
for (var _ in dict) {
return false
}
return true
});

exports.$$delete = $$delete$1;
exports.size = size;
exports.isEmpty = isEmpty;
exports.forEach = forEach;
exports.forEachWithKey = forEachWithKey;
exports.mapValues = mapValues;
Expand Down
10 changes: 9 additions & 1 deletion lib/js/Stdlib_Map.js
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
'use strict';


function isEmpty(map) {
return map.size === 0;
}

exports.isEmpty = isEmpty;
/* No side effect */
10 changes: 9 additions & 1 deletion lib/js/Stdlib_Set.js
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
'use strict';


function isEmpty(set) {
return set.size === 0;
}

exports.isEmpty = isEmpty;
/* No side effect */
14 changes: 14 additions & 0 deletions lib/js/Stdlib_String.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,21 @@ function searchOpt(s, re) {

}

function isEmpty(s) {
return s.length === 0;
}

function capitalize(s) {
if (s.length === 0) {
return s;
} else {
return s[0].toUpperCase() + s.slice(1);
}
}

exports.indexOfOpt = indexOfOpt;
exports.lastIndexOfOpt = lastIndexOfOpt;
exports.searchOpt = searchOpt;
exports.isEmpty = isEmpty;
exports.capitalize = capitalize;
/* No side effect */
2 changes: 2 additions & 0 deletions runtime/Stdlib_Array.res
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ let fromInitializer = (~length, f) =>

@get external length: array<'a> => int = "length"

let isEmpty = arr => arr->length === 0

let rec equalFromIndex = (a, b, i, eq, len) =>
if i === len {
true
Expand Down
22 changes: 20 additions & 2 deletions runtime/Stdlib_Array.resi
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ someArray->Array.length == 2
@get
external length: array<'a> => int = "length"

/**
`isEmpty(array)` returns `true` if the array is empty (has length 0), `false` otherwise.

## Examples

```rescript
[]->Array.isEmpty->assertEqual(true)
[1, 2, 3]->Array.isEmpty->assertEqual(false)

let emptyArray = []
emptyArray->Array.isEmpty->assertEqual(true)

let nonEmptyArray = ["hello"]
nonEmptyArray->Array.isEmpty->assertEqual(false)
```
*/
let isEmpty: array<'a> => bool

// TODO: Docs
@deprecated("Use `copyWithin` instead") @send
external copyAllWithin: (array<'a>, ~target: int) => array<'a> = "copyWithin"
Expand Down Expand Up @@ -909,7 +927,7 @@ external mapWithIndex: (array<'a>, ('a, int) => 'b) => array<'b> = "map"
/**
`reduce(xs, init, fn)`

Applies `fn` to each element of `xs` from beginning to end. Function `fn` has two parameters: the item from the list and an accumulator; which starts with a value of `init`. `reduce` returns the final value of the accumulator.
Applies `fn` to each element of `xs` from beginning to end. Function `fn` has two parameters: the item from the list and an "accumulator"; which starts with a value of `init`. `reduce` returns the final value of the accumulator.

## Examples

Expand All @@ -928,7 +946,7 @@ let reduce: (array<'a>, 'b, ('b, 'a) => 'b) => 'b
/**
`reduceWithIndex(x, init, fn)`

Applies `fn` to each element of `xs` from beginning to end. Function `fn` has three parameters: the item from the array and an accumulator, which starts with a value of `init` and the index of each element. `reduceWithIndex` returns the final value of the accumulator.
Applies `fn` to each element of `xs` from beginning to end. Function `fn` has three parameters: the item from the array and an "accumulator", which starts with a value of `init` and the index of each element. `reduceWithIndex` returns the final value of the accumulator.

## Examples

Expand Down
51 changes: 37 additions & 14 deletions runtime/Stdlib_Dict.res
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,45 @@ let delete = (dict, string) => {

@val external copy: (@as(json`{}`) _, dict<'a>) => dict<'a> = "Object.assign"

let forEach = (dict, f) => {
dict->valuesToArray->Stdlib_Array.forEach(value => f(value))
}
// Use %raw to support for..in which is a ~10% faster than .forEach
let forEach: (dict<'a>, 'a => unit) => unit = %raw(`(dict, f) => {
for (var i in dict) {
f(dict[i]);
}
}`)

@inline
let forEachWithKey = (dict, f) => {
dict->keysToArray->Stdlib_Array.forEach(key => f(dict->getUnsafe(key), key))
}
// Use %raw to support for..in which is a ~10% faster than .forEach
let forEachWithKey: (dict<'a>, ('a, string) => unit) => unit = %raw(`(dict, f) => {
for (var i in dict) {
f(dict[i], i);
}
}`)

let mapValues = (dict, f) => {
let target = make()
dict->forEachWithKey((value, key) => {
target->set(key, f(value))
})
target
}
// Use %raw to support for..in which is a ~10% faster than .forEach
let mapValues: (dict<'a>, 'a => 'b) => dict<'b> = %raw(`(dict, f) => {
var target = {}, i;
for (i in dict) {
target[i] = f(dict[i]);
}
return target;
}`)

// Use %raw to support for..in which is a ~10% faster than Object.keys
let size: dict<'a> => int = %raw(`(dict) => {
var size = 0, i;
for (i in dict) {
size++;
}
return size;
}`)

// Use %raw to support for..in which is a 2x faster than Object.keys
let isEmpty: dict<'a> => bool = %raw(`(dict) => {
for (var _ in dict) {
return false
}
return true
}`)

external has: (dict<'a>, string) => bool = "%dict_has"

Expand Down
Loading
Loading