Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

- Add `Dict.has` and double `Dict.forEachWithKey`/`Dict.mapValues` performance. https://github.com/rescript-lang/rescript/pull/7316
- Add popover attributes to JsxDOM.domProps. https://github.com/rescript-lang/rescript/pull/7317
- Add `Array.removeInPlace` helper based on `splice`. https://github.com/rescript-lang/rescript/pull/7321
- Add `inert` attribute to `JsxDOM.domProps`. https://github.com/rescript-lang/rescript/pull/7326

#### :boom: Breaking Change
Expand Down
3 changes: 3 additions & 0 deletions runtime/Stdlib_Array.res
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ external splice: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => u
external toSpliced: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => array<'a> =
"toSpliced"

@send
external removeInPlace: (array<'a>, int, @as(1) _) => unit = "splice"

@send external with: (array<'a>, int, 'a) => array<'a> = "with"

@send external unshift: (array<'a>, 'a) => unit = "unshift"
Expand Down
3 changes: 3 additions & 0 deletions runtime/Stdlib_Array.resi
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ external splice: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => u
external toSpliced: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => array<'a> =
"toSpliced"

@send
external removeInPlace: (array<'a>, int, @as(1) _) => unit = "splice"

Copy link
Member

Choose a reason for hiding this comment

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

nitpicking, but wouldn't it be better to move the tests here as docstring tests? At least they would help documenting the function.

Whatever we decide to do, I'd add some documentation here anyway, at least to document that the second argument is an index. Maybe it's a sign we should use a labelled argument here (~start, ~index?) like the other functions with indices here, what do you guys think? @zth ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a documentation comment 👍

Regarding labeled arguments I think it's consistent for the array API to not use it when we have a single argument which is an index. But it would definitely make sense if we had more arguments like:

@send
external removeMultipleInPlace: (array<'a>, ~start: int, ~number: int) => unit = "splice"

Copy link
Member

Choose a reason for hiding this comment

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

many functions with just one int parameter in the Stdlib.Array module are labeled, it might be worth making all of this more consistant, but this could definitely be in another PR.

@send external with: (array<'a>, int, 'a) => array<'a> = "with"

/**
Expand Down
73 changes: 73 additions & 0 deletions tests/tests/src/core/Core_ArrayTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,79 @@ Test.run([
"last - empty"
], Stdlib_Array.last([]), eq, undefined);

let array = [];

array.splice(1, 0, "foo");

Test.run([
[
"Core_ArrayTests.res",
116,
22,
49
],
"splice - Insert no delete"
], array, eq, ["foo"]);

let array$1 = [
"bar",
"baz"
];

Test.run([
[
"Core_ArrayTests.res",
122,
15,
43
],
"splice - Insert and delete"
], [
(array$1.splice(1, 1, "foo"), undefined),
array$1
], eq, [
undefined,
[
"bar",
"foo"
]
]);

let array$2 = [];

array$2.splice(0, 1);

Test.run([
[
"Core_ArrayTests.res",
132,
22,
45
],
"removeInPlace - empty"
], array$2, eq, []);

let array$3 = [
"Hello",
"Hi",
"Good bye"
];

array$3.splice(1, 1);

Test.run([
[
"Core_ArrayTests.res",
138,
22,
51
],
"removeInPlace - from middle"
], array$3, eq, [
"Hello",
"Good bye"
]);

export {
eq,
}
Expand Down
33 changes: 33 additions & 0 deletions tests/tests/src/core/Core_ArrayTests.res
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,36 @@ Test.run(

Test.run(__POS_OF__("last - with items"), [1, 2, 3]->Array.last, eq, Some(3))
Test.run(__POS_OF__("last - empty"), []->Array.last, eq, None)

{
let array = []
array->Array.splice(~start=1, ~remove=0, ~insert=["foo"])
Test.run(__POS_OF__("splice - Insert no delete"), array, eq, ["foo"])
}

{
let array = ["bar", "baz"]
Test.run(
__POS_OF__("splice - Insert and delete"),
(array->Array.splice(~start=1, ~remove=1, ~insert=["foo"]), array),
eq,
(
// Even though original .splice returns an array with the removed items,
// the binding returns unit so there's no confusion about it mutating the original array.
(),
["bar", "foo"],
),
)
}

{
let array = []
array->Array.removeInPlace(0)
Test.run(__POS_OF__("removeInPlace - empty"), array, eq, [])
}

{
let array = ["Hello", "Hi", "Good bye"]
array->Array.removeInPlace(1)
Test.run(__POS_OF__("removeInPlace - from middle"), array, eq, ["Hello", "Good bye"])
}
Copy link
Member

Choose a reason for hiding this comment

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

should we keep these tests here given they're already in the docstring tests?

Copy link
Member Author

@DZakh DZakh Mar 14, 2025

Choose a reason for hiding this comment

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

Wow, are they automated?

Copy link
Member

Choose a reason for hiding this comment

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

@DZakh yes, that's the whole point of those docstring tests :)

Loading