aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Attard <robert.attard@mail.mcgill.ca>2022-07-27 09:46:26 -0400
committerLouis Pilfold <louis@lpil.uk>2022-07-27 18:37:46 +0100
commit4b3b5d972650e6d7580aed479fd0404c37371cf6 (patch)
tree416cc36bbb7eecb46da8fcfd89c60cb790268b14
parent2d991bd9439ba837ee238972f3f97d762513bcbc (diff)
downloadgleam_stdlib-4b3b5d972650e6d7580aed479fd0404c37371cf6.tar.gz
gleam_stdlib-4b3b5d972650e6d7580aed479fd0404c37371cf6.zip
inclusive list.range and iterator.range
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/gleam/iterator.gleam43
-rw-r--r--src/gleam/list.gleam8
-rw-r--r--test/gleam/iterator_test.gleam16
-rw-r--r--test/gleam/list_test.gleam12
5 files changed, 47 insertions, 33 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5adc01..d471cee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
ranges when compiled to JavaScript.
- Fixed a bug where the `list` module's `contains`, `any`, and `all` could
exhaust the stack when compiling to JavaScript.
+- `list.range` and `iterator.range` return values are now inclusive of both start and end bounds.
## v0.22.1 - 2022-06-27
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index 92729a1..6290b05 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -1,6 +1,8 @@
+import gleam/int
import gleam/list
import gleam/map.{Map}
import gleam/option.{None, Option, Some}
+import gleam/order
// Internal private representation of an Iterator
type Action(element) {
@@ -447,29 +449,40 @@ pub fn cycle(iterator: Iterator(a)) -> Iterator(a) {
///
/// ```gleam
/// > range(from: 1, to: 5) |> to_list
-/// [1, 2, 3, 4]
+/// [1, 2, 3, 4, 5]
///
/// > range(from: 1, to: -2) |> to_list
-/// [1, 0, -1]
+/// [1, 0, -1, -2]
///
/// > range(from: 0, to: 0) |> to_list
-/// []
+/// [0]
/// ```
///
pub fn range(from start: Int, to stop: Int) -> Iterator(Int) {
- let increment = case start < stop {
- True -> 1
- False -> -1
- }
-
- let next_step = fn(current) {
- case current == stop {
- True -> Done
- False -> Next(current, current + increment)
- }
+ case int.compare(start, stop) {
+ order.Eq -> once(fn() { start })
+ order.Gt ->
+ unfold(
+ from: start,
+ with: fn(current) {
+ case current < stop {
+ False -> Next(current, current - 1)
+ True -> Done
+ }
+ },
+ )
+
+ order.Lt ->
+ unfold(
+ from: start,
+ with: fn(current) {
+ case current > stop {
+ False -> Next(current, current + 1)
+ True -> Done
+ }
+ },
+ )
}
-
- unfold(start, next_step)
}
fn do_find(continuation: fn() -> Action(a), f: fn(a) -> Bool) -> Result(a, Nil) {
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index 1a9d5ce..a46278a 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -1038,13 +1038,13 @@ pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) {
///
/// ```gleam
/// > range(0, 0)
-/// []
+/// [0]
///
/// > range(0, 5)
-/// [0, 1, 2, 3, 4]
+/// [0, 1, 2, 3, 4, 5]
///
/// > range(1, -5)
-/// [1, 0, -1, -2, -3, -4]
+/// [1, 0, -1, -2, -3, -4, -5]
/// ```
///
pub fn range(from start: Int, to stop: Int) -> List(Int) {
@@ -1053,7 +1053,7 @@ pub fn range(from start: Int, to stop: Int) -> List(Int) {
fn tail_recursive_range(start: Int, stop: Int, acc: List(Int)) -> List(Int) {
case int.compare(start, stop) {
- order.Eq -> reverse(acc)
+ order.Eq -> reverse([stop, ..acc])
order.Gt -> tail_recursive_range(start - 1, stop, [start, ..acc])
order.Lt -> tail_recursive_range(start + 1, stop, [start, ..acc])
}
diff --git a/test/gleam/iterator_test.gleam b/test/gleam/iterator_test.gleam
index 8f035d9..976e209 100644
--- a/test/gleam/iterator_test.gleam
+++ b/test/gleam/iterator_test.gleam
@@ -222,19 +222,19 @@ pub fn range_test() {
|> should.equal(expected)
}
- test(0, 0, [])
- test(1, 1, [])
- test(-1, -1, [])
- test(0, 1, [0])
- test(0, 5, [0, 1, 2, 3, 4])
- test(1, -5, [1, 0, -1, -2, -3, -4])
+ test(0, 0, [0])
+ test(1, 1, [1])
+ test(-1, -1, [-1])
+ test(0, 1, [0, 1])
+ test(0, 5, [0, 1, 2, 3, 4, 5])
+ test(1, -5, [1, 0, -1, -2, -3, -4, -5])
}
pub fn drop_test() {
iterator.range(0, 10)
|> iterator.drop(5)
|> iterator.to_list
- |> should.equal([5, 6, 7, 8, 9])
+ |> should.equal([5, 6, 7, 8, 9, 10])
}
type Cat {
@@ -392,7 +392,7 @@ pub fn last_test() {
iterator.range(1, 10)
|> iterator.last
- |> should.equal(Ok(9))
+ |> should.equal(Ok(10))
}
pub fn empty_test() {
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index 566aa94..1ea4f42 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -472,22 +472,22 @@ pub fn index_map_test() {
pub fn range_test() {
list.range(0, 0)
- |> should.equal([])
+ |> should.equal([0])
list.range(1, 1)
- |> should.equal([])
+ |> should.equal([1])
list.range(-1, -1)
- |> should.equal([])
+ |> should.equal([-1])
list.range(0, 1)
- |> should.equal([0])
+ |> should.equal([0, 1])
list.range(0, 5)
- |> should.equal([0, 1, 2, 3, 4])
+ |> should.equal([0, 1, 2, 3, 4, 5])
list.range(1, -5)
- |> should.equal([1, 0, -1, -2, -3, -4])
+ |> should.equal([1, 0, -1, -2, -3, -4, -5])
// This should not overflow the stack
list.range(1, 100_000)