Skip to content
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

add Int.range and Int.rangeWithOptions #52

Merged
merged 4 commits into from
Mar 6, 2023
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- Fixed type signatures of `reduce` and `reduceWithIndex`. https://github.com/rescript-association/rescript-core/pull/49
- Add `panic`/`Error.panic`. https://github.com/rescript-association/rescript-core/pull/72
- The globally available `null` value now originates from `Nullable` and not `Null`, just like the globally available `undefined` value does. https://github.com/rescript-association/rescript-core/pull/88
- Add `Int.range` and `Int.rangeWithOptions`, https://github.com/rescript-association/rescript-core/pull/52

### Documentation

Expand Down
39 changes: 39 additions & 0 deletions src/Core__Int.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Generated by ReScript, PLEASE EDIT WITH CARE

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

function fromString(radix, x) {
var maybeInt = radix !== undefined ? parseInt(x, radix) : parseInt(x);
Expand All @@ -10,6 +12,41 @@ function fromString(radix, x) {
}
}

function rangeWithOptions(start, end, options) {
var isInverted = start > end;
var n = options.step;
var step;
if (n !== undefined) {
if (n !== 0) {
step = n;
} else {
if (start !== end) {
throw new RangeError("Incorrect range arguments");
}
step = n;
}
} else {
step = isInverted ? -1 : 1;
}
var length;
if (isInverted === step >= 0) {
length = 0;
} else if (step === 0) {
length = options.inclusive === true ? 1 : 0;
} else {
var range = isInverted ? start - end | 0 : end - start | 0;
var range$1 = options.inclusive === true ? range + 1 | 0 : range;
length = Math.ceil(range$1 / Pervasives.abs(step)) | 0;
}
return Core__Array.fromInitializer(length, (function (i) {
return start + Math.imul(i, step) | 0;
}));
}

function range(start, end) {
return rangeWithOptions(start, end, {});
}

var Constants = {
minValue: -2147483648,
maxValue: 2147483647
Expand All @@ -18,5 +55,7 @@ var Constants = {
export {
Constants ,
fromString ,
range ,
rangeWithOptions ,
}
/* No side effect */
26 changes: 26 additions & 0 deletions src/Core__Int.res
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,29 @@ let fromString = (~radix=?, x) => {
}

external mod: (int, int) => int = "%modint"

type rangeOptions = {step?: int, inclusive?: bool}
let rangeWithOptions = (start, end, options) => {
let isInverted = start > end

let step = switch options.step {
| None => isInverted ? -1 : 1
| Some(0) if start !== end =>
Core__Error.raise(Core__Error.RangeError.make("Incorrect range arguments"))
| Some(n) => n
}

let length = if isInverted === (step >= 0) {
0 // infinite because step goes in opposite direction of end
} else if step == 0 {
options.inclusive === Some(true) ? 1 : 0
} else {
let range = isInverted ? start - end : end - start
let range = options.inclusive === Some(true) ? range + 1 : range
ceil(float(range) /. float(abs(step)))->Core__Float.toInt
}

Core__Array.fromInitializer(~length, i => start + i * step)
}

let range = (start, end) => rangeWithOptions(start, end, {})
54 changes: 54 additions & 0 deletions src/Core__Int.resi
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,57 @@ Int.mod(7, 4) == 3
```
*/
external mod: (int, int) => int = "%modint"

/**
`range(start, end)` returns an int array of the sequence of integers in the
range `[start, end)`. That is, including `start` but excluding `end`.

If `start < end` the sequence will be increasing in steps of 1.

If `start > end` the sequence will be decreasing in steps of -1.

This is equivalent to `rangeWithOptions` with `inclusive` set to `false` and
`step` set to `1` if `start < end` and `-1` otherwise.

## Examples

```rescript
Int.range(3, 6) == [3, 4, 5]
Int.range(-3, -1) == [-3, -2]
Int.range(3, 1) == [3, 2]
```
*/
let range: (int, int) => array<int>

/**
The options for `rangeWithOptions`.
*/
type rangeOptions = {step?: int, inclusive?: bool}

/**
`rangeWithOptions(start, end, options)` is like `range`, but with `step` and
`inclusive` options configurable.

If `step` is set, the sequence will increase or decrease by that amount for each
step. If `start < end` and `step` is negative, or vice versa, an empty array is
returned since the sequence would otherwise never reach or exceed the end value
and hence be infinite. If `step` is `0` and `start !=` end, a `RangeError` is
raised as the sequence would never reach or exceed the end value and hence be
infinite.

If `inclusive` is set to `true`, the sequence will include `end` if `step` is
set such that the sequence includes it.

## Examples

```rescript
Int.rangeWithOptions(3, 7, {step: 2}) == [3, 5]
Int.rangeWithOptions(3, 7, {step: 2, inclusive: true}) == [3, 5, 7]
Int.rangeWithOptions(3, 6, {step: -2}) // RangeError
```

## Exceptions

- Raises `RangeError` if `step == 0 && start != end`.
*/
let rangeWithOptions: (int, int, rangeOptions) => array<int>
Loading