Skip to content

Commit 094e6ae

Browse files
committed
feat(int): add range and rangeWithOptions
1 parent a976a8c commit 094e6ae

File tree

7 files changed

+756
-3
lines changed

7 files changed

+756
-3
lines changed

src/Core__Int.mjs

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
22

3+
import * as Pervasives from "rescript/lib/es6/pervasives.js";
4+
import * as Core__Array from "./Core__Array.mjs";
35

46
function fromString(radix, x) {
57
var maybeInt = radix !== undefined ? parseInt(x, radix) : parseInt(x);
@@ -10,6 +12,41 @@ function fromString(radix, x) {
1012
}
1113
}
1214

15+
function rangeWithOptions(start, end, options) {
16+
var isInverted = start > end;
17+
var n = options.step;
18+
var step;
19+
if (n !== undefined) {
20+
if (n !== 0) {
21+
step = n;
22+
} else {
23+
if (start !== end) {
24+
throw new RangeError("Incorrect range arguments");
25+
}
26+
step = n;
27+
}
28+
} else {
29+
step = isInverted ? -1 : 1;
30+
}
31+
var length;
32+
if (isInverted === step >= 0) {
33+
length = 0;
34+
} else if (step === 0) {
35+
length = options.inclusive === true ? 1 : 0;
36+
} else {
37+
var range = isInverted ? start - end | 0 : end - start | 0;
38+
var range$1 = options.inclusive === true ? range + 1 | 0 : range;
39+
length = Math.ceil(range$1 / Pervasives.abs(step)) | 0;
40+
}
41+
return Core__Array.fromInitializer(length, (function (i) {
42+
return start + Math.imul(i, step) | 0;
43+
}));
44+
}
45+
46+
function range(start, end) {
47+
return rangeWithOptions(start, end, {});
48+
}
49+
1350
var Constants = {
1451
minValue: -2147483648,
1552
maxValue: 2147483647
@@ -18,5 +55,7 @@ var Constants = {
1855
export {
1956
Constants ,
2057
fromString ,
58+
range ,
59+
rangeWithOptions ,
2160
}
2261
/* No side effect */

src/Core__Int.res

+26
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,29 @@ let fromString = (~radix=?, x) => {
3535
}
3636

3737
external mod: (int, int) => int = "%modint"
38+
39+
type rangeOptions = {step?: int, inclusive?: bool}
40+
let rangeWithOptions = (start, end, options) => {
41+
let isInverted = start > end
42+
43+
let step = switch options.step {
44+
| None => isInverted ? -1 : 1
45+
| Some(0) if start !== end =>
46+
Core__Error.raise(Core__Error.RangeError.make("Incorrect range arguments"))
47+
| Some(n) => n
48+
}
49+
50+
let length = if isInverted === (step >= 0) {
51+
0 // infinite because step goes in opposite direction of end
52+
} else if step == 0 {
53+
options.inclusive === Some(true) ? 1 : 0
54+
} else {
55+
let range = isInverted ? start - end : end - start
56+
let range = options.inclusive === Some(true) ? range + 1 : range
57+
ceil(float(range) /. float(abs(step)))->Core__Float.toInt
58+
}
59+
60+
Core__Array.fromInitializer(~length, i => start + i * step)
61+
}
62+
63+
let range = (start, end) => rangeWithOptions(start, end, {})

src/Core__Int.resi

+54
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,57 @@ Int.mod(7, 4) == 3
268268
```
269269
*/
270270
external mod: (int, int) => int = "%modint"
271+
272+
/**
273+
`range(start, end)` returns an int array of the sequence of integeres in the
274+
range `[start, end)`. That is, including `start` but excluding `end`.
275+
276+
If `start < end` the sequence will be increasing in steps of 1.
277+
278+
If `start < end` the sequence will be decreasing in steps of -1.
279+
280+
This is equivalent to `rangeWithOptions` with `inclusive` set to `false` and
281+
`step` set to `1` if `start < end` and `-1` otherwise.
282+
283+
## Examples
284+
285+
```rescript
286+
Int.range(3, 6) == [3, 4, 5]
287+
Int.range(-3, -1) == [-3, -2]
288+
Int.range(3, 1) == [3, 2]
289+
```
290+
*/
291+
let range: (int, int) => array<int>
292+
293+
/**
294+
The options for `rangeWithOptions`.
295+
*/
296+
type rangeOptions = {step?: int, inclusive?: bool}
297+
298+
/**
299+
`rangeWithOptions(start, end, options)` is like `range`, but with `step` and
300+
`inlusive` options configurable.
301+
302+
If `step` is set, the sequence will increase or decrease by that amount for each
303+
step. If `start < end` and `step` is negative, or vice versa, an empty array is
304+
returned since the sequence would otherwise never reach or exceed the end value
305+
and hence be infinite. If `step` is `0` and `start !=` end, a `RangeError` is
306+
raised as the sequence would never reach or exceed the end value and hence be
307+
infinite.
308+
309+
If `inclusive` is set to `true`, the sequence will include `end` if `step` is
310+
set such that the sequence includes it.
311+
312+
## Examples
313+
314+
```rescript
315+
Int.rangeWithOptions(3, 7, {step: 2}) == [3, 5]
316+
Int.rangeWithOptions(3, 7, {step: 2, inclusive: true}) == [3, 5, 7]
317+
Int.rangeWithOptions(3, 6, {step: -2}) // RangeError
318+
```
319+
320+
## Exceptions
321+
322+
- Raises `RangeError` if `step == 0 && start != end`.
323+
*/
324+
let rangeWithOptions: (int, int, rangeOptions) => array<int>

0 commit comments

Comments
 (0)