aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiacomo Cavalieri <giacomo.cavalieri@icloud.com>2024-11-06 16:15:01 +0100
committerLouis Pilfold <louis@lpil.uk>2024-11-06 15:43:31 +0000
commit959aa176b8de5a004cfc1e331095a4bd3c6875ec (patch)
tree47aba32242c91b5a8f41b25e6a6d8525b6abfbb7 /src
parent226a2ee1cfd1d6d408530c218207e6a12e31433f (diff)
downloadgleam_stdlib-959aa176b8de5a004cfc1e331095a4bd3c6875ec.tar.gz
gleam_stdlib-959aa176b8de5a004cfc1e331095a4bd3c6875ec.zip
fix-721
Diffstat (limited to 'src')
-rw-r--r--src/gleam/bit_array.gleam15
-rw-r--r--src/gleam/dict.gleam44
-rw-r--r--src/gleam/float.gleam13
-rw-r--r--src/gleam/int.gleam25
-rw-r--r--src/gleam/iterator.gleam651
-rw-r--r--src/gleam/list.gleam601
-rw-r--r--src/gleam/option.gleam64
-rw-r--r--src/gleam/result.gleam8
-rw-r--r--src/gleam/string.gleam21
9 files changed, 722 insertions, 720 deletions
diff --git a/src/gleam/bit_array.gleam b/src/gleam/bit_array.gleam
index 14db902..2c70d14 100644
--- a/src/gleam/bit_array.gleam
+++ b/src/gleam/bit_array.gleam
@@ -48,20 +48,20 @@ pub fn slice(
/// Tests to see whether a bit array is valid UTF-8.
///
pub fn is_utf8(bits: BitArray) -> Bool {
- do_is_utf8(bits)
+ is_utf8_loop(bits)
}
@target(erlang)
-fn do_is_utf8(bits: BitArray) -> Bool {
+fn is_utf8_loop(bits: BitArray) -> Bool {
case bits {
<<>> -> True
- <<_:utf8, rest:bytes>> -> do_is_utf8(rest)
+ <<_:utf8, rest:bytes>> -> is_utf8_loop(rest)
_ -> False
}
}
@target(javascript)
-fn do_is_utf8(bits: BitArray) -> Bool {
+fn is_utf8_loop(bits: BitArray) -> Bool {
case to_string(bits) {
Ok(_) -> True
_ -> False
@@ -158,11 +158,11 @@ pub fn base16_decode(input: String) -> Result(BitArray, Nil)
/// ```
///
pub fn inspect(input: BitArray) -> String {
- do_inspect(input, "<<") <> ">>"
+ inspect_loop(input, "<<") <> ">>"
}
@external(javascript, "../gleam_stdlib.mjs", "bit_array_inspect")
-fn do_inspect(input: BitArray, accumulator: String) -> String {
+fn inspect_loop(input: BitArray, accumulator: String) -> String {
case input {
<<>> -> accumulator
@@ -181,8 +181,7 @@ fn do_inspect(input: BitArray, accumulator: String) -> String {
}
let accumulator = accumulator <> int.to_string(x) <> suffix
-
- do_inspect(rest, accumulator)
+ inspect_loop(rest, accumulator)
}
_ -> accumulator
diff --git a/src/gleam/dict.gleam b/src/gleam/dict.gleam
index 10b5544..4697c8d 100644
--- a/src/gleam/dict.gleam
+++ b/src/gleam/dict.gleam
@@ -223,7 +223,7 @@ pub fn keys(dict: Dict(k, v)) -> List(k) {
@external(erlang, "maps", "keys")
fn do_keys(dict: Dict(k, v)) -> List(k) {
let list_of_pairs = to_list(dict)
- do_keys_acc(list_of_pairs, [])
+ do_keys_loop(list_of_pairs, [])
}
fn reverse_and_concat(remaining: List(a), accumulator: List(a)) -> List(a) {
@@ -233,10 +233,10 @@ fn reverse_and_concat(remaining: List(a), accumulator: List(a)) -> List(a) {
}
}
-fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) {
+fn do_keys_loop(list: List(#(k, v)), acc: List(k)) -> List(k) {
case list {
[] -> reverse_and_concat(acc, [])
- [first, ..rest] -> do_keys_acc(rest, [first.0, ..acc])
+ [first, ..rest] -> do_keys_loop(rest, [first.0, ..acc])
}
}
@@ -260,13 +260,13 @@ pub fn values(dict: Dict(k, v)) -> List(v) {
@external(erlang, "maps", "values")
fn do_values(dict: Dict(k, v)) -> List(v) {
let list_of_pairs = to_list(dict)
- do_values_acc(list_of_pairs, [])
+ do_values_loop(list_of_pairs, [])
}
-fn do_values_acc(list: List(#(k, v)), acc: List(v)) -> List(v) {
+fn do_values_loop(list: List(#(k, v)), acc: List(v)) -> List(v) {
case list {
[] -> reverse_and_concat(acc, [])
- [first, ..rest] -> do_values_acc(rest, [first.1, ..acc])
+ [first, ..rest] -> do_values_loop(rest, [first.1, ..acc])
}
}
@@ -302,8 +302,8 @@ fn do_filter(f: fn(k, v) -> Bool, dict: Dict(k, v)) -> Dict(k, v) {
_ -> dict
}
}
- dict
- |> fold(from: new(), with: insert)
+
+ fold(dict, from: new(), with: insert)
}
/// Creates a new dict from a given dict, only including any entries for which the
@@ -329,10 +329,10 @@ pub fn take(from dict: Dict(k, v), keeping desired_keys: List(k)) -> Dict(k, v)
@external(erlang, "maps", "with")
fn do_take(desired_keys: List(k), dict: Dict(k, v)) -> Dict(k, v) {
- insert_taken(dict, desired_keys, new())
+ do_take_loop(dict, desired_keys, new())
}
-fn insert_taken(
+fn do_take_loop(
dict: Dict(k, v),
desired_keys: List(k),
acc: Dict(k, v),
@@ -345,7 +345,7 @@ fn insert_taken(
}
case desired_keys {
[] -> acc
- [first, ..rest] -> insert_taken(dict, rest, insert(acc, first))
+ [first, ..rest] -> do_take_loop(dict, rest, insert(acc, first))
}
}
@@ -470,13 +470,6 @@ pub fn upsert(
|> insert(dict, key, _)
}
-fn do_fold(list: List(#(k, v)), initial: acc, fun: fn(acc, k, v) -> acc) -> acc {
- case list {
- [] -> initial
- [#(k, v), ..rest] -> do_fold(rest, fun(initial, k, v), fun)
- }
-}
-
/// Combines all entries into a single value by calling a given function on each
/// one.
///
@@ -507,9 +500,18 @@ pub fn fold(
from initial: acc,
with fun: fn(acc, k, v) -> acc,
) -> acc {
- dict
- |> to_list
- |> do_fold(initial, fun)
+ fold_loop(to_list(dict), initial, fun)
+}
+
+fn fold_loop(
+ list: List(#(k, v)),
+ initial: acc,
+ fun: fn(acc, k, v) -> acc,
+) -> acc {
+ case list {
+ [] -> initial
+ [#(k, v), ..rest] -> fold_loop(rest, fun(initial, k, v), fun)
+ }
}
/// Calls a function for each key and value in a dict, discarding the return
diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam
index 7030caa..a7d6dc8 100644
--- a/src/gleam/float.gleam
+++ b/src/gleam/float.gleam
@@ -403,14 +403,13 @@ pub fn negate(x: Float) -> Float {
/// ```
///
pub fn sum(numbers: List(Float)) -> Float {
- numbers
- |> do_sum(0.0)
+ sum_loop(numbers, 0.0)
}
-fn do_sum(numbers: List(Float), initial: Float) -> Float {
+fn sum_loop(numbers: List(Float), initial: Float) -> Float {
case numbers {
+ [x, ..rest] -> sum_loop(rest, x +. initial)
[] -> initial
- [x, ..rest] -> do_sum(rest, x +. initial)
}
}
@@ -426,14 +425,14 @@ fn do_sum(numbers: List(Float), initial: Float) -> Float {
pub fn product(numbers: List(Float)) -> Float {
case numbers {
[] -> 1.0
- _ -> do_product(numbers, 1.0)
+ _ -> product_loop(numbers, 1.0)
}
}
-fn do_product(numbers: List(Float), initial: Float) -> Float {
+fn product_loop(numbers: List(Float), initial: Float) -> Float {
case numbers {
+ [x, ..rest] -> product_loop(rest, x *. initial)
[] -> initial
- [x, ..rest] -> do_product(rest, x *. initial)
}
}
diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam
index 5d60b6e..de039d5 100644
--- a/src/gleam/int.gleam
+++ b/src/gleam/int.gleam
@@ -427,14 +427,13 @@ pub fn negate(x: Int) -> Int {
/// ```
///
pub fn sum(numbers: List(Int)) -> Int {
- numbers
- |> do_sum(0)
+ sum_loop(numbers, 0)
}
-fn do_sum(numbers: List(Int), initial: Int) -> Int {
+fn sum_loop(numbers: List(Int), initial: Int) -> Int {
case numbers {
+ [x, ..rest] -> sum_loop(rest, x + initial)
[] -> initial
- [x, ..rest] -> do_sum(rest, x + initial)
}
}
@@ -450,14 +449,14 @@ fn do_sum(numbers: List(Int), initial: Int) -> Int {
pub fn product(numbers: List(Int)) -> Int {
case numbers {
[] -> 1
- _ -> do_product(numbers, 1)
+ _ -> product_loop(numbers, 1)
}
}
-fn do_product(numbers: List(Int), initial: Int) -> Int {
+fn product_loop(numbers: List(Int), initial: Int) -> Int {
case numbers {
+ [x, ..rest] -> product_loop(rest, x * initial)
[] -> initial
- [x, ..rest] -> do_product(rest, x * initial)
}
}
@@ -479,14 +478,14 @@ fn do_product(numbers: List(Int), initial: Int) -> Int {
pub fn digits(x: Int, base: Int) -> Result(List(Int), Nil) {
case base < 2 {
True -> Error(Nil)
- False -> Ok(do_digits(x, base, []))
+ False -> Ok(digits_loop(x, base, []))
}
}
-fn do_digits(x: Int, base: Int, acc: List(Int)) -> List(Int) {
+fn digits_loop(x: Int, base: Int, acc: List(Int)) -> List(Int) {
case absolute_value(x) < base {
True -> [x, ..acc]
- False -> do_digits(x / base, base, [x % base, ..acc])
+ False -> digits_loop(x / base, base, [x % base, ..acc])
}
}
@@ -513,15 +512,15 @@ fn do_digits(x: Int, base: Int, acc: List(Int)) -> List(Int) {
pub fn undigits(numbers: List(Int), base: Int) -> Result(Int, Nil) {
case base < 2 {
True -> Error(Nil)
- False -> do_undigits(numbers, base, 0)
+ False -> undigits_loop(numbers, base, 0)
}
}
-fn do_undigits(numbers: List(Int), base: Int, acc: Int) -> Result(Int, Nil) {
+fn undigits_loop(numbers: List(Int), base: Int, acc: Int) -> Result(Int, Nil) {
case numbers {
[] -> Ok(acc)
[digit, ..] if digit >= base -> Error(Nil)
- [digit, ..rest] -> do_undigits(rest, base, acc * base + digit)
+ [digit, ..rest] -> undigits_loop(rest, base, acc * base + digit)
}
}
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index 3232a12..812436b 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -38,19 +38,6 @@ fn stop() -> Action(element) {
Stop
}
-// Creating Iterators
-fn do_unfold(
- initial: acc,
- f: fn(acc) -> Step(element, acc),
-) -> fn() -> Action(element) {
- fn() {
- case f(initial) {
- Next(x, acc) -> Continue(x, do_unfold(acc, f))
- Done -> Stop
- }
- }
-}
-
/// Creates an iterator from a given function and accumulator.
///
/// The function is called on the accumulator and returns either `Done`,
@@ -77,10 +64,23 @@ pub fn unfold(
with f: fn(acc) -> Step(element, acc),
) -> Iterator(element) {
initial
- |> do_unfold(f)
+ |> unfold_loop(f)
|> Iterator
}
+// Creating Iterators
+fn unfold_loop(
+ initial: acc,
+ f: fn(acc) -> Step(element, acc),
+) -> fn() -> Action(element) {
+ fn() {
+ case f(initial) {
+ Next(x, acc) -> Continue(x, unfold_loop(acc, f))
+ Done -> Stop
+ }
+ }
+}
+
/// Creates an iterator that yields values created by calling a given function
/// repeatedly.
///
@@ -131,7 +131,7 @@ pub fn from_list(list: List(element)) -> Iterator(element) {
}
// Consuming Iterators
-fn do_transform(
+fn transform_loop(
continuation: fn() -> Action(a),
state: acc,
f: fn(acc, a) -> Step(b, acc),
@@ -143,7 +143,7 @@ fn do_transform(
case f(state, el) {
Done -> Stop
Next(yield, next_state) ->
- Continue(yield, do_transform(next, next_state, f))
+ Continue(yield, transform_loop(next, next_state, f))
}
}
}
@@ -171,17 +171,17 @@ pub fn transform(
from initial: acc,
with f: fn(acc, a) -> Step(b, acc),
) -> Iterator(b) {
- do_transform(iterator.continuation, initial, f)
+ transform_loop(iterator.continuation, initial, f)
|> Iterator
}
-fn do_fold(
+fn fold_loop(
continuation: fn() -> Action(e),
f: fn(acc, e) -> acc,
accumulator: acc,
) -> acc {
case continuation() {
- Continue(elem, next) -> do_fold(next, f, f(accumulator, elem))
+ Continue(elem, next) -> fold_loop(next, f, f(accumulator, elem))
Stop -> accumulator
}
}
@@ -209,7 +209,7 @@ pub fn fold(
with f: fn(acc, e) -> acc,
) -> acc {
iterator.continuation
- |> do_fold(f, initial)
+ |> fold_loop(f, initial)
}
// TODO: test
@@ -270,19 +270,6 @@ pub fn step(iterator: Iterator(e)) -> Step(e, Iterator(e)) {
}
}
-fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) {
- fn() {
- case desired > 0 {
- False -> Stop
- True ->
- case continuation() {
- Stop -> Stop
- Continue(e, next) -> Continue(e, do_take(next, desired - 1))
- }
- }
- }
-}
-
/// Creates an iterator that only yields the first `desired` elements.
///
/// If the iterator does not have enough elements all of them are yielded.
@@ -305,18 +292,20 @@ fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) {
///
pub fn take(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
iterator.continuation
- |> do_take(desired)
+ |> take_loop(desired)
|> Iterator
}
-fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) {
- case continuation() {
- Stop -> Stop
- Continue(e, next) ->
- case desired > 0 {
- True -> do_drop(next, desired - 1)
- False -> Continue(e, next)
- }
+fn take_loop(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) {
+ fn() {
+ case desired > 0 {
+ False -> Stop
+ True ->
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) -> Continue(e, take_loop(next, desired - 1))
+ }
+ }
}
}
@@ -346,16 +335,18 @@ fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) {
/// ```
///
pub fn drop(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
- fn() { do_drop(iterator.continuation, desired) }
+ fn() { drop_loop(iterator.continuation, desired) }
|> Iterator
}
-fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) {
- fn() {
- case continuation() {
- Stop -> Stop
- Continue(e, continuation) -> Continue(f(e), do_map(continuation, f))
- }
+fn drop_loop(continuation: fn() -> Action(e), desired: Int) -> Action(e) {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) ->
+ case desired > 0 {
+ True -> drop_loop(next, desired - 1)
+ False -> Continue(e, next)
+ }
}
}
@@ -378,24 +369,15 @@ fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) {
///
pub fn map(over iterator: Iterator(a), with f: fn(a) -> b) -> Iterator(b) {
iterator.continuation
- |> do_map(f)
+ |> map_loop(f)
|> Iterator
}
-fn do_map2(
- continuation1: fn() -> Action(a),
- continuation2: fn() -> Action(b),
- with fun: fn(a, b) -> c,
-) -> fn() -> Action(c) {
+fn map_loop(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) {
fn() {
- case continuation1() {
+ case continuation() {
Stop -> Stop
- Continue(a, next_a) ->
- case continuation2() {
- Stop -> Stop
- Continue(b, next_b) ->
- Continue(fun(a, b), do_map2(next_a, next_b, fun))
- }
+ Continue(e, continuation) -> Continue(f(e), map_loop(continuation, f))
}
}
}
@@ -428,14 +410,25 @@ pub fn map2(
iterator2: Iterator(b),
with fun: fn(a, b) -> c,
) -> Iterator(c) {
- do_map2(iterator1.continuation, iterator2.continuation, fun)
+ map2_loop(iterator1.continuation, iterator2.continuation, fun)
|> Iterator
}
-fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) {
- case first() {
- Continue(e, first) -> Continue(e, fn() { do_append(first, second) })
- Stop -> second()
+fn map2_loop(
+ continuation1: fn() -> Action(a),
+ continuation2: fn() -> Action(b),
+ with fun: fn(a, b) -> c,
+) -> fn() -> Action(c) {
+ fn() {
+ case continuation1() {
+ Stop -> Stop
+ Continue(a, next_a) ->
+ case continuation2() {
+ Stop -> Stop
+ Continue(b, next_b) ->
+ Continue(fun(a, b), map2_loop(next_a, next_b, fun))
+ }
+ }
}
}
@@ -454,15 +447,14 @@ fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) {
/// ```
///
pub fn append(to first: Iterator(a), suffix second: Iterator(a)) -> Iterator(a) {
- fn() { do_append(first.continuation, second.continuation) }
+ fn() { append_loop(first.continuation, second.continuation) }
|> Iterator
}
-fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) {
- case flattened() {
- Stop -> Stop
- Continue(it, next_iterator) ->
- do_append(it.continuation, fn() { do_flatten(next_iterator) })
+fn append_loop(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) {
+ case first() {
+ Continue(e, first) -> Continue(e, fn() { append_loop(first, second) })
+ Stop -> second()
}
}
@@ -482,10 +474,18 @@ fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) {
/// ```
///
pub fn flatten(iterator: Iterator(Iterator(a))) -> Iterator(a) {
- fn() { do_flatten(iterator.continuation) }
+ fn() { flatten_loop(iterator.continuation) }
|> Iterator
}
+fn flatten_loop(flattened: fn() -> Action(Iterator(a))) -> Action(a) {
+ case flattened() {
+ Stop -> Stop
+ Continue(it, next_iterator) ->
+ append_loop(it.continuation, fn() { flatten_loop(next_iterator) })
+ }
+}
+
/// Joins a list of iterators into a single iterator.
///
/// This function does not evaluate the elements of the iterator, the
@@ -532,20 +532,6 @@ pub fn flat_map(
|> flatten
}
-fn do_filter(
- continuation: fn() -> Action(e),
- predicate: fn(e) -> Bool,
-) -> Action(e) {
- case continuation() {
- Stop -> Stop
- Continue(e, iterator) ->
- case predicate(e) {
- True -> Continue(e, fn() { do_filter(iterator, predicate) })
- False -> do_filter(iterator, predicate)
- }
- }
-}
-
/// Creates an iterator from an existing iterator and a predicate function.
///
/// The new iterator will contain elements from the first iterator for which
@@ -569,20 +555,20 @@ pub fn filter(
iterator: Iterator(a),
keeping predicate: fn(a) -> Bool,
) -> Iterator(a) {
- fn() { do_filter(iterator.continuation, predicate) }
+ fn() { filter_loop(iterator.continuation, predicate) }
|> Iterator
}
-fn do_filter_map(
- continuation: fn() -> Action(a),
- f: fn(a) -> Result(b, c),
-) -> Action(b) {
+fn filter_loop(
+ continuation: fn() -> Action(e),
+ predicate: fn(e) -> Bool,
+) -> Action(e) {
case continuation() {
Stop -> Stop
- Continue(e, next) ->
- case f(e) {
- Ok(e) -> Continue(e, fn() { do_filter_map(next, f) })
- Error(_) -> do_filter_map(next, f)
+ Continue(e, iterator) ->
+ case predicate(e) {
+ True -> Continue(e, fn() { filter_loop(iterator, predicate) })
+ False -> filter_loop(iterator, predicate)
}
}
}
@@ -613,10 +599,24 @@ pub fn filter_map(
iterator: Iterator(a),
keeping_with f: fn(a) -> Result(b, c),
) -> Iterator(b) {
- fn() { do_filter_map(iterator.continuation, f) }
+ fn() { filter_map_loop(iterator.continuation, f) }
|> Iterator
}
+fn filter_map_loop(
+ continuation: fn() -> Action(a),
+ f: fn(a) -> Result(b, c),
+) -> Action(b) {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) ->
+ case f(e) {
+ Ok(e) -> Continue(e, fn() { filter_map_loop(next, f) })
+ Error(_) -> filter_map_loop(next, f)
+ }
+ }
+}
+
/// Creates an iterator that repeats a given iterator infinitely.
///
/// ## Examples
@@ -675,17 +675,6 @@ pub fn range(from start: Int, to stop: Int) -> Iterator(Int) {
}
}
-fn do_find(continuation: fn() -> Action(a), f: fn(a) -> Bool) -> Result(a, Nil) {
- case continuation() {
- Stop -> Error(Nil)
- Continue(e, next) ->
- case f(e) {
- True -> Ok(e)
- False -> do_find(next, f)
- }
- }
-}
-
/// Finds the first element in a given iterator for which the given function returns
/// `True`.
///
@@ -714,19 +703,19 @@ pub fn find(
one_that is_desired: fn(a) -> Bool,
) -> Result(a, Nil) {
haystack.continuation
- |> do_find(is_desired)
+ |> find_loop(is_desired)
}
-fn do_find_map(
+fn find_loop(
continuation: fn() -> Action(a),
- f: fn(a) -> Result(b, c),
-) -> Result(b, Nil) {
+ f: fn(a) -> Bool,
+) -> Result(a, Nil) {
case continuation() {
Stop -> Error(Nil)
Continue(e, next) ->
case f(e) {
- Ok(e) -> Ok(e)
- Error(_) -> do_find_map(next, f)
+ True -> Ok(e)
+ False -> find_loop(next, f)
}
}
}
@@ -759,19 +748,20 @@ pub fn find_map(
one_that is_desired: fn(a) -> Result(b, c),
) -> Result(b, Nil) {
haystack.continuation
- |> do_find_map(is_desired)
+ |> find_map_loop(is_desired)
}
-fn do_index(
- continuation: fn() -> Action(element),
- next: Int,
-) -> fn() -> Action(#(element, Int)) {
- fn() {
- case continuation() {
- Stop -> Stop
- Continue(e, continuation) ->
- Continue(#(e, next), do_index(continuation, next + 1))
- }
+fn find_map_loop(
+ continuation: fn() -> Action(a),
+ f: fn(a) -> Result(b, c),
+) -> Result(b, Nil) {
+ case continuation() {
+ Stop -> Error(Nil)
+ Continue(e, next) ->
+ case f(e) {
+ Ok(e) -> Ok(e)
+ Error(_) -> find_map_loop(next, f)
+ }
}
}
@@ -786,10 +776,23 @@ fn do_index(
///
pub fn index(over iterator: Iterator(element)) -> Iterator(#(element, Int)) {
iterator.continuation
- |> do_index(0)
+ |> index_loop(0)
|> Iterator
}
+fn index_loop(
+ continuation: fn() -> Action(element),
+ next: Int,
+) -> fn() -> Action(#(element, Int)) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, continuation) ->
+ Continue(#(e, next), index_loop(continuation, next + 1))
+ }
+ }
+}
+
/// Creates an iterator that infinitely applies a function to a value.
///
/// ## Examples
@@ -806,22 +809,6 @@ pub fn iterate(
unfold(initial, fn(element) { Next(element, f(element)) })
}
-fn do_take_while(
- continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> fn() -> Action(element) {
- fn() {
- case continuation() {
- Stop -> Stop
- Continue(e, next) ->
- case predicate(e) {
- False -> Stop
- True -> Continue(e, do_take_while(next, predicate))
- }
- }
- }
-}
-
/// Creates an iterator that yields elements while the predicate returns `True`.
///
/// ## Examples
@@ -838,21 +825,23 @@ pub fn take_while(
satisfying predicate: fn(element) -> Bool,
) -> Iterator(element) {
iterator.continuation
- |> do_take_while(predicate)
+ |> take_while_loop(predicate)
|> Iterator
}
-fn do_drop_while(
+fn take_while_loop(
continuation: fn() -> Action(element),
predicate: fn(element) -> Bool,
-) -> Action(element) {
- case continuation() {
- Stop -> Stop
- Continue(e, next) ->
- case predicate(e) {
- False -> Continue(e, next)
- True -> do_drop_while(next, predicate)
- }
+) -> fn() -> Action(element) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) ->
+ case predicate(e) {
+ False -> Stop
+ True -> Continue(e, take_while_loop(next, predicate))
+ }
+ }
}
}
@@ -872,23 +861,21 @@ pub fn drop_while(
in iterator: Iterator(element),
satisfying predicate: fn(element) -> Bool,
) -> Iterator(element) {
- fn() { do_drop_while(iterator.continuation, predicate) }
+ fn() { drop_while_loop(iterator.continuation, predicate) }
|> Iterator
}
-fn do_scan(
+fn drop_while_loop(
continuation: fn() -> Action(element),
- f: fn(acc, element) -> acc,
- accumulator: acc,
-) -> fn() -> Action(acc) {
- fn() {
- case continuation() {
- Stop -> Stop
- Continue(el, next) -> {
- let accumulated = f(accumulator, el)
- Continue(accumulated, do_scan(next, f, accumulated))
+ predicate: fn(element) -> Bool,
+) -> Action(element) {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) ->
+ case predicate(e) {
+ False -> Continue(e, next)
+ True -> drop_while_loop(next, predicate)
}
- }
}
}
@@ -912,23 +899,22 @@ pub fn scan(
with f: fn(acc, element) -> acc,
) -> Iterator(acc) {
iterator.continuation
- |> do_scan(f, initial)
+ |> scan_loop(f, initial)
|> Iterator
}
-fn do_zip(
- left: fn() -> Action(a),
- right: fn() -> Action(b),
-) -> fn() -> Action(#(a, b)) {
+fn scan_loop(
+ continuation: fn() -> Action(element),
+ f: fn(acc, element) -> acc,
+ accumulator: acc,
+) -> fn() -> Action(acc) {
fn() {
- case left() {
+ case continuation() {
Stop -> Stop
- Continue(el_left, next_left) ->
- case right() {
- Stop -> Stop
- Continue(el_right, next_right) ->
- Continue(#(el_left, el_right), do_zip(next_left, next_right))
- }
+ Continue(el, next) -> {
+ let accumulated = f(accumulator, el)
+ Continue(accumulated, scan_loop(next, f, accumulated))
+ }
}
}
}
@@ -946,45 +932,31 @@ fn do_zip(
/// ```
///
pub fn zip(left: Iterator(a), right: Iterator(b)) -> Iterator(#(a, b)) {
- do_zip(left.continuation, right.continuation)
+ zip_loop(left.continuation, right.continuation)
|> Iterator
}
-// Result of collecting a single chunk by key
-type Chunk(element, key) {
- AnotherBy(List(element), key, element, fn() -> Action(element))
- LastBy(List(element))
-}
-
-fn next_chunk(
- continuation: fn() -> Action(element),
- f: fn(element) -> key,
- previous_key: key,
- current_chunk: List(element),
-) -> Chunk(element, key) {
- case continuation() {
- Stop -> LastBy(list.reverse(current_chunk))
- Continue(e, next) -> {
- let key = f(e)
- case key == previous_key {
- True -> next_chunk(next, f, key, [e, ..current_chunk])
- False -> AnotherBy(list.reverse(current_chunk), key, e, next)
- }
+fn zip_loop(
+ left: fn() -> Action(a),
+ right: fn() -> Action(b),
+) -> fn() -> Action(#(a, b)) {
+ fn() {
+ case left() {
+ Stop -> Stop
+ Continue(el_left, next_left) ->
+ case right() {
+ Stop -> Stop
+ Continue(el_right, next_right) ->
+ Continue(#(el_left, el_right), zip_loop(next_left, next_right))
+ }
}
}
}
-fn do_chunk(
- continuation: fn() -> Action(element),
- f: fn(element) -> key,
- previous_key: key,
- previous_element: element,
-) -> Action(List(element)) {
- case next_chunk(continuation, f, previous_key, [previous_element]) {
- LastBy(chunk) -> Continue(chunk, stop)
- AnotherBy(chunk, key, el, next) ->
- Continue(chunk, fn() { do_chunk(next, f, key, el) })
- }
+// Result of collecting a single chunk by key
+type Chunk(element, key) {
+ AnotherBy(List(element), key, element, fn() -> Action(element))
+ LastBy(List(element))
}
/// Creates an iterator that emits chunks of elements
@@ -1006,54 +978,43 @@ pub fn chunk(
fn() {
case iterator.continuation() {
Stop -> Stop
- Continue(e, next) -> do_chunk(next, f, f(e), e)
+ Continue(e, next) -> chunk_loop(next, f, f(e), e)
}
}
|> Iterator
}
-// Result of collecting a single sized chunk
-type SizedChunk(element) {
- Another(List(element), fn() -> Action(element))
- Last(List(element))
- NoMore
+fn chunk_loop(
+ continuation: fn() -> Action(element),
+ f: fn(element) -> key,
+ previous_key: key,
+ previous_element: element,
+) -> Action(List(element)) {
+ case next_chunk(continuation, f, previous_key, [previous_element]) {
+ LastBy(chunk) -> Continue(chunk, stop)
+ AnotherBy(chunk, key, el, next) ->
+ Continue(chunk, fn() { chunk_loop(next, f, key, el) })
+ }
}
-fn next_sized_chunk(
+fn next_chunk(
continuation: fn() -> Action(element),
- left: Int,
+ f: fn(element) -> key,
+ previous_key: key,
current_chunk: List(element),
-) -> SizedChunk(element) {
+) -> Chunk(element, key) {
case continuation() {
- Stop ->
- case current_chunk {
- [] -> NoMore
- remaining -> Last(list.reverse(remaining))
- }
+ Stop -> LastBy(list.reverse(current_chunk))
Continue(e, next) -> {
- let chunk = [e, ..current_chunk]
- case left > 1 {
- False -> Another(list.reverse(chunk), next)
- True -> next_sized_chunk(next, left - 1, chunk)
+ let key = f(e)
+ case key == previous_key {
+ True -> next_chunk(next, f, key, [e, ..current_chunk])
+ False -> AnotherBy(list.reverse(current_chunk), key, e, next)
}
}
}
}
-fn do_sized_chunk(
- continuation: fn() -> Action(element),
- count: Int,
-) -> fn() -> Action(List(element)) {
- fn() {
- case next_sized_chunk(continuation, count, []) {
- NoMore -> Stop
- Last(chunk) -> Continue(chunk, stop)
- Another(chunk, next_element) ->
- Continue(chunk, do_sized_chunk(next_element, count))
- }
- }
-}
-
/// Creates an iterator that emits chunks of given size.
///
/// If the last chunk does not have `count` elements, it is yielded
@@ -1082,19 +1043,48 @@ pub fn sized_chunk(
into count: Int,
) -> Iterator(List(element)) {
iterator.continuation
- |> do_sized_chunk(count)
+ |> sized_chunk_loop(count)
|> Iterator
}
-fn do_intersperse(
+fn sized_chunk_loop(
continuation: fn() -> Action(element),
- separator: element,
-) -> Action(element) {
+ count: Int,
+) -> fn() -> Action(List(element)) {
+ fn() {
+ case next_sized_chunk(continuation, count, []) {
+ NoMore -> Stop
+ Last(chunk) -> Continue(chunk, stop)
+ Another(chunk, next_element) ->
+ Continue(chunk, sized_chunk_loop(next_element, count))
+ }
+ }
+}
+
+// Result of collecting a single sized chunk
+type SizedChunk(element) {
+ Another(List(element), fn() -> Action(element))
+ Last(List(element))
+ NoMore
+}
+
+fn next_sized_chunk(
+ continuation: fn() -> Action(element),
+ left: Int,
+ current_chunk: List(element),
+) -> SizedChunk(element) {
case continuation() {
- Stop -> Stop
+ Stop ->
+ case current_chunk {
+ [] -> NoMore
+ remaining -> Last(list.reverse(remaining))
+ }
Continue(e, next) -> {
- let next_interspersed = fn() { do_intersperse(next, separator) }
- Continue(separator, fn() { Continue(e, next_interspersed) })
+ let chunk = [e, ..current_chunk]
+ case left > 1 {
+ False -> Another(list.reverse(chunk), next)
+ True -> next_sized_chunk(next, left - 1, chunk)
+ }
}
}
}
@@ -1132,23 +1122,22 @@ pub fn intersperse(
fn() {
case iterator.continuation() {
Stop -> Stop
- Continue(e, next) -> Continue(e, fn() { do_intersperse(next, elem) })
+ Continue(e, next) -> Continue(e, fn() { intersperse_loop(next, elem) })
}
}
|> Iterator
}
-fn do_any(
+fn intersperse_loop(
continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> Bool {
+ separator: element,
+) -> Action(element) {
case continuation() {
- Stop -> False
- Continue(e, next) ->
- case predicate(e) {
- True -> True
- False -> do_any(next, predicate)
- }
+ Stop -> Stop
+ Continue(e, next) -> {
+ let next_interspersed = fn() { intersperse_loop(next, separator) }
+ Continue(separator, fn() { Continue(e, next_interspersed) })
+ }
}
}
@@ -1184,19 +1173,19 @@ pub fn any(
satisfying predicate: fn(element) -> Bool,
) -> Bool {
iterator.continuation
- |> do_any(predicate)
+ |> any_loop(predicate)
}
-fn do_all(
+fn any_loop(
continuation: fn() -> Action(element),
predicate: fn(element) -> Bool,
) -> Bool {
case continuation() {
- Stop -> True
+ Stop -> False
Continue(e, next) ->
case predicate(e) {
- True -> do_all(next, predicate)
- False -> False
+ True -> True
+ False -> any_loop(next, predicate)
}
}
}
@@ -1233,24 +1222,20 @@ pub fn all(
satisfying predicate: fn(element) -> Bool,
) -> Bool {
iterator.continuation
- |> do_all(predicate)
-}
-
-fn update_group_with(el: element) -> fn(Option(List(element))) -> List(element) {
- fn(maybe_group) {
- case maybe_group {
- Some(group) -> [el, ..group]
- None -> [el]
- }
- }
+ |> all_loop(predicate)
}
-fn group_updater(
- f: fn(element) -> key,
-) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) {
- fn(groups, elem) {
- groups
- |> dict.upsert(f(elem), update_group_with(elem))
+fn all_loop(
+ continuation: fn() -> Action(element),
+ predicate: fn(element) -> Bool,
+) -> Bool {
+ case continuation() {
+ Stop -> True
+ Continue(e, next) ->
+ case predicate(e) {
+ True -> all_loop(next, predicate)
+ False -> False
+ }
}
}
@@ -1276,6 +1261,24 @@ pub fn group(
|> dict.map_values(fn(_, group) { list.reverse(group) })
}
+fn group_updater(
+ f: fn(element) -> key,
+) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) {
+ fn(groups, elem) {
+ groups
+ |> dict.upsert(f(elem), update_group_with(elem))
+ }
+}
+
+fn update_group_with(el: element) -> fn(Option(List(element))) -> List(element) {
+ fn(maybe_group) {
+ case maybe_group {
+ Some(group) -> [el, ..group]
+ None -> [el]
+ }
+ }
+}
+
/// This function acts similar to fold, but does not take an initial state.
/// Instead, it starts from the first yielded element
/// and combines it with each subsequent element in turn using the given function.
@@ -1304,7 +1307,7 @@ pub fn reduce(
case iterator.continuation() {
Stop -> Error(Nil)
Continue(e, next) ->
- do_fold(next, f, e)
+ fold_loop(next, f, e)
|> Ok
}
}
@@ -1372,17 +1375,6 @@ pub fn single(elem: element) -> Iterator(element) {
once(fn() { elem })
}
-fn do_interleave(
- current: fn() -> Action(element),
- next: fn() -> Action(element),
-) -> Action(element) {
- case current() {
- Stop -> next()
- Continue(e, next_other) ->
- Continue(e, fn() { do_interleave(next, next_other) })
- }
-}
-
/// Creates an iterator that alternates between the two given iterators
/// until both have run out.
///
@@ -1406,22 +1398,18 @@ pub fn interleave(
left: Iterator(element),
with right: Iterator(element),
) -> Iterator(element) {
- fn() { do_interleave(left.continuation, right.continuation) }
+ fn() { interleave_loop(left.continuation, right.continuation) }
|> Iterator
}
-fn do_fold_until(
- continuation: fn() -> Action(e),
- f: fn(acc, e) -> list.ContinueOrStop(acc),
- accumulator: acc,
-) -> acc {
- case continuation() {
- Stop -> accumulator
- Continue(elem, next) ->
- case f(accumulator, elem) {
- list.Continue(accumulator) -> do_fold_until(next, f, accumulator)
- list.Stop(accumulator) -> accumulator
- }
+fn interleave_loop(
+ current: fn() -> Action(element),
+ next: fn() -> Action(element),
+) -> Action(element) {
+ case current() {
+ Stop -> next()
+ Continue(e, next_other) ->
+ Continue(e, fn() { interleave_loop(next, next_other) })
}
}
@@ -1455,22 +1443,21 @@ pub fn fold_until(
with f: fn(acc, e) -> list.ContinueOrStop(acc),
) -> acc {
iterator.continuation
- |> do_fold_until(f, initial)
+ |> fold_until_loop(f, initial)
}
-fn do_try_fold(
- over continuation: fn() -> Action(a),
- with f: fn(acc, a) -> Result(acc, err),
- from accumulator: acc,
-) -> Result(acc, err) {
+fn fold_until_loop(
+ continuation: fn() -> Action(e),
+ f: fn(acc, e) -> list.ContinueOrStop(acc),
+ accumulator: acc,
+) -> acc {
case continuation() {
- Stop -> Ok(accumulator)
- Continue(elem, next) -> {
+ Stop -> accumulator
+ Continue(elem, next) ->
case f(accumulator, elem) {
- Ok(result) -> do_try_fold(next, f, result)
- Error(_) as error -> error
+ list.Continue(accumulator) -> fold_until_loop(next, f, accumulator)
+ list.Stop(accumulator) -> accumulator
}
- }
}
}
@@ -1499,7 +1486,23 @@ pub fn try_fold(
with f: fn(acc, e) -> Result(acc, err),
) -> Result(acc, err) {
iterator.continuation
- |> do_try_fold(f, initial)
+ |> try_fold_loop(f, initial)
+}
+
+fn try_fold_loop(
+ over continuation: fn() -> Action(a),
+ with f: fn(acc, a) -> Result(acc, err),
+ from accumulator: acc,
+) -> Result(acc, err) {
+ case continuation() {
+ Stop -> Ok(accumulator)
+ Continue(elem, next) -> {
+ case f(accumulator, elem) {
+ Ok(result) -> try_fold_loop(next, f, result)
+ Error(_) as error -> error
+ }
+ }
+ }
}
/// Returns the first element yielded by the given iterator, if it exists,
@@ -1552,13 +1555,6 @@ pub fn at(in iterator: Iterator(e), get index: Int) -> Result(e, Nil) {
|> first
}
-fn do_length(over continuation: fn() -> Action(e), with length: Int) -> Int {
- case continuation() {
- Stop -> length
- Continue(_, next) -> do_length(next, length + 1)
- }
-}
-
/// Counts the number of elements in the given iterator.
///
/// This function has to traverse the entire iterator to count its elements,
@@ -1578,7 +1574,14 @@ fn do_length(over continuation: fn() -> Action(e), with length: Int) -> Int {
///
pub fn length(over iterator: Iterator(e)) -> Int {
iterator.continuation
- |> do_length(0)
+ |> length_loop(0)
+}
+
+fn length_loop(over continuation: fn() -> Action(e), with length: Int) -> Int {
+ case continuation() {
+ Stop -> length
+ Continue(_, next) -> length_loop(next, length + 1)
+ }
}
/// Traverse an iterator, calling a function on each element.
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index c363cda..97084db 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -124,13 +124,13 @@ pub fn count(list: List(a), where predicate: fn(a) -> Bool) -> Int {
///
@external(erlang, "lists", "reverse")
pub fn reverse(list: List(a)) -> List(a) {
- do_reverse(list, [])
+ reverse_loop(list, [])
}
-fn do_reverse(remaining: List(a), accumulator: List(a)) -> List(a) {
+fn reverse_loop(remaining: List(a), accumulator: List(a)) -> List(a) {
case remaining {
[] -> accumulator
- [item, ..rest] -> do_reverse(rest, [item, ..accumulator])
+ [item, ..rest] -> reverse_loop(rest, [item, ..accumulator])
}
}
@@ -299,19 +299,6 @@ pub fn group(list: List(v), by key: fn(v) -> k) -> Dict(k, List(v)) {
fold(list, dict.new(), update_group(key))
}
-fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
- case list {
- [] -> reverse(acc)
- [first, ..rest] -> {
- let new_acc = case fun(first) {
- True -> [first, ..acc]
- False -> acc
- }
- do_filter(rest, fun, new_acc)
- }
- }
-}
-
/// Returns a new list containing only the elements from the first list for
/// which the given functions returns `True`.
///
@@ -328,22 +315,18 @@ fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
/// ```
///
pub fn filter(list: List(a), keeping predicate: fn(a) -> Bool) -> List(a) {
- do_filter(list, predicate, [])
+ filter_loop(list, predicate, [])
}
-fn do_filter_map(
- list: List(a),
- fun: fn(a) -> Result(b, e),
- acc: List(b),
-) -> List(b) {
+fn filter_loop(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
case list {
[] -> reverse(acc)
[first, ..rest] -> {
let new_acc = case fun(first) {
- Ok(first) -> [first, ..acc]
- Error(_) -> acc
+ True -> [first, ..acc]
+ False -> acc
}
- do_filter_map(rest, fun, new_acc)
+ filter_loop(rest, fun, new_acc)
}
}
}
@@ -364,13 +347,23 @@ fn do_filter_map(
/// ```
///
pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) {
- do_filter_map(list, fun, [])
+ filter_map_loop(list, fun, [])
}
-fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
+fn filter_map_loop(
+ list: List(a),
+ fun: fn(a) -> Result(b, e),
+ acc: List(b),
+) -> List(b) {
case list {
[] -> reverse(acc)
- [first, ..rest] -> do_map(rest, fun, [fun(first), ..acc])
+ [first, ..rest] -> {
+ let new_acc = case fun(first) {
+ Ok(first) -> [first, ..acc]
+ Error(_) -> acc
+ }
+ filter_map_loop(rest, fun, new_acc)
+ }
}
}
@@ -385,7 +378,14 @@ fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
/// ```
///
pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) {
- do_map(list, fun, [])
+ map_loop(list, fun, [])
+}
+
+fn map_loop(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
+ case list {
+ [] -> reverse(acc)
+ [first, ..rest] -> map_loop(rest, fun, [fun(first), ..acc])
+ }
}
/// Combines two lists into a single list using the given function.
@@ -405,10 +405,10 @@ pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) {
/// ```
///
pub fn map2(list1: List(a), list2: List(b), with fun: fn(a, b) -> c) -> List(c) {
- do_map2(list1, list2, fun, [])
+ map2_loop(list1, list2, fun, [])
}
-fn do_map2(
+fn map2_loop(
list1: List(a),
list2: List(b),
fun: fn(a, b) -> c,
@@ -416,7 +416,7 @@ fn do_map2(
) -> List(c) {
case list1, list2 {
[], _ | _, [] -> reverse(acc)
- [a, ..as_], [b, ..bs] -> do_map2(as_, bs, fun, [fun(a, b), ..acc])
+ [a, ..as_], [b, ..bs] -> map2_loop(as_, bs, fun, [fun(a, b), ..acc])
}
}
@@ -446,21 +446,6 @@ pub fn map_fold(
|> pair.map_second(reverse)
}
-fn do_index_map(
- list: List(a),
- fun: fn(a, Int) -> b,
- index: Int,
- acc: List(b),
-) -> List(b) {
- case list {
- [] -> reverse(acc)
- [first, ..rest] -> {
- let acc = [fun(first, index), ..acc]
- do_index_map(rest, fun, index + 1, acc)
- }
- }
-}
-
/// Returns a new list containing only the elements of the first list after the
/// function has been applied to each one and their index.
///
@@ -475,21 +460,21 @@ fn do_index_map(
/// ```
///
pub fn index_map(list: List(a), with fun: fn(a, Int) -> b) -> List(b) {
- do_index_map(list, fun, 0, [])
+ index_map_loop(list, fun, 0, [])
}
-fn do_try_map(
+fn index_map_loop(
list: List(a),
- fun: fn(a) -> Result(b, e),
+ fun: fn(a, Int) -> b,
+ index: Int,
acc: List(b),
-) -> Result(List(b), e) {
+) -> List(b) {
case list {
- [] -> Ok(reverse(acc))
- [first, ..rest] ->
- case fun(first) {
- Ok(first) -> do_try_map(rest, fun, [first, ..acc])
- Error(error) -> Error(error)
- }
+ [] -> reverse(acc)
+ [first, ..rest] -> {
+ let acc = [fun(first, index), ..acc]
+ index_map_loop(rest, fun, index + 1, acc)
+ }
}
}
@@ -529,7 +514,22 @@ pub fn try_map(
over list: List(a),
with fun: fn(a) -> Result(b, e),
) -> Result(List(b), e) {
- do_try_map(list, fun, [])
+ try_map_loop(list, fun, [])
+}
+
+fn try_map_loop(
+ list: List(a),
+ fun: fn(a) -> Result(b, e),
+ acc: List(b),
+) -> Result(List(b), e) {
+ case list {
+ [] -> Ok(reverse(acc))
+ [first, ..rest] ->
+ case fun(first) {
+ Ok(first) -> try_map_loop(rest, fun, [first, ..acc])
+ Error(error) -> Error(error)
+ }
+ }
}
/// Returns a list that is the given list with up to the given number of
@@ -563,17 +563,6 @@ pub fn drop(from list: List(a), up_to n: Int) -> List(a) {
}
}
-fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) {
- case n <= 0 {
- True -> reverse(acc)
- False ->
- case list {
- [] -> reverse(acc)
- [first, ..rest] -> do_take(rest, n - 1, [first, ..acc])
- }
- }
-}
-
/// Returns a list containing the first given number of elements from the given
/// list.
///
@@ -595,7 +584,18 @@ fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) {
/// ```
///
pub fn take(from list: List(a), up_to n: Int) -> List(a) {
- do_take(list, n, [])
+ take_loop(list, n, [])
+}
+
+fn take_loop(list: List(a), n: Int, acc: List(a)) -> List(a) {
+ case n <= 0 {
+ True -> reverse(acc)
+ False ->
+ case list {
+ [] -> reverse(acc)
+ [first, ..rest] -> take_loop(rest, n - 1, [first, ..acc])
+ }
+ }
}
/// Returns a new empty list.
@@ -645,13 +645,13 @@ pub fn wrap(item: a) -> List(a) {
///
@external(erlang, "lists", "append")
pub fn append(first: List(a), second: List(a)) -> List(a) {
- do_append(reverse(first), second)
+ append_loop(reverse(first), second)
}
-fn do_append(first: List(a), second: List(a)) -> List(a) {
+fn append_loop(first: List(a), second: List(a)) -> List(a) {
case first {
[] -> second
- [item, ..rest] -> do_append(rest, [item, ..second])
+ [item, ..rest] -> append_loop(rest, [item, ..second])
}
}
@@ -680,14 +680,6 @@ fn reverse_and_prepend(list prefix: List(a), to suffix: List(a)) -> List(a) {
}
}
-fn do_concat(lists: List(List(a)), acc: List(a)) -> List(a) {
- case lists {
- [] -> reverse(acc)
- [list, ..further_lists] ->
- do_concat(further_lists, reverse_and_prepend(list: list, to: acc))
- }
-}
-
/// Joins a list of lists into a single list.
///
/// This function traverses all elements twice.
@@ -701,7 +693,15 @@ fn do_concat(lists: List(List(a)), acc: List(a)) -> List(a) {
///
@deprecated("Use `list.flatten` instead.")
pub fn concat(lists: List(List(a))) -> List(a) {
- do_concat(lists, [])
+ concat_loop(lists, [])
+}
+
+fn concat_loop(lists: List(List(a)), acc: List(a)) -> List(a) {
+ case lists {
+ [] -> reverse(acc)
+ [list, ..further_lists] ->
+ concat_loop(further_lists, reverse_and_prepend(list: list, to: acc))
+ }
}
/// This is the same as `concat`: it joins a list of lists into a single
@@ -717,7 +717,7 @@ pub fn concat(lists: List(List(a))) -> List(a) {
/// ```
///
pub fn flatten(lists: List(List(a))) -> List(a) {
- do_concat(lists, [])
+ concat_loop(lists, [])
}
/// Maps the list with the given function into a list of lists, and then flattens it.
@@ -775,19 +775,6 @@ pub fn fold_right(
}
}
-fn do_index_fold(
- over: List(a),
- acc: acc,
- with: fn(acc, a, Int) -> acc,
- index: Int,
-) -> acc {
- case over {
- [] -> acc
- [first, ..rest] ->
- do_index_fold(rest, with(acc, first, index), with, index + 1)
- }
-}
-
/// Like fold but the folding function also receives the index of the current element.
///
/// ## Examples
@@ -802,7 +789,20 @@ pub fn index_fold(
from initial: acc,
with fun: fn(acc, a, Int) -> acc,
) -> acc {
- do_index_fold(list, initial, fun, 0)
+ index_fold_loop(list, initial, fun, 0)
+}
+
+fn index_fold_loop(
+ over: List(a),
+ acc: acc,
+ with: fn(acc, a, Int) -> acc,
+ index: Int,
+) -> acc {
+ case over {
+ [] -> acc
+ [first, ..rest] ->
+ index_fold_loop(rest, with(acc, first, index), with, index + 1)
+ }
}
/// A variant of fold that might fail.
@@ -1019,14 +1019,6 @@ pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
}
}
-fn do_zip(one: List(a), other: List(b), acc: List(#(a, b))) -> List(#(a, b)) {
- case one, other {
- [first_one, ..rest_one], [first_other, ..rest_other] ->
- do_zip(rest_one, rest_other, [#(first_one, first_other), ..acc])
- _, _ -> reverse(acc)
- }
-}
-
/// Takes two lists and returns a single list of 2-element tuples.
///
/// If one of the lists is longer than the other, the remaining elements from
@@ -1055,7 +1047,15 @@ fn do_zip(one: List(a), other: List(b), acc: List(#(a, b))) -> List(#(a, b)) {
/// ```
///
pub fn zip(list: List(a), with other: List(b)) -> List(#(a, b)) {
- do_zip(list, other, [])
+ zip_loop(list, other, [])
+}
+
+fn zip_loop(one: List(a), other: List(b), acc: List(#(a, b))) -> List(#(a, b)) {
+ case one, other {
+ [first_one, ..rest_one], [first_other, ..rest_other] ->
+ zip_loop(rest_one, rest_other, [#(first_one, first_other), ..acc])
+ _, _ -> reverse(acc)
+ }
}
/// Takes two lists and returns a single list of 2-element tuples.
@@ -1094,18 +1094,6 @@ pub fn strict_zip(
}
}
-fn do_unzip(
- input: List(#(a, b)),
- one: List(a),
- other: List(b),
-) -> #(List(a), List(b)) {
- case input {
- [] -> #(reverse(one), reverse(other))
- [#(first_one, first_other), ..rest] ->
- do_unzip(rest, [first_one, ..one], [first_other, ..other])
- }
-}
-
/// Takes a single list of 2-element tuples and returns two lists.
///
/// ## Examples
@@ -1121,13 +1109,18 @@ fn do_unzip(
/// ```
///
pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) {
- do_unzip(input, [], [])
+ unzip_loop(input, [], [])
}
-fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) {
- case list {
- [] -> reverse(acc)
- [x, ..rest] -> do_intersperse(rest, separator, [x, separator, ..acc])
+fn unzip_loop(
+ input: List(#(a, b)),
+ one: List(a),
+ other: List(b),
+) -> #(List(a), List(b)) {
+ case input {
+ [] -> #(reverse(one), reverse(other))
+ [#(first_one, first_other), ..rest] ->
+ unzip_loop(rest, [first_one, ..one], [first_other, ..other])
}
}
@@ -1150,7 +1143,14 @@ fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) {
pub fn intersperse(list: List(a), with elem: a) -> List(a) {
case list {
[] | [_] -> list
- [x, ..rest] -> do_intersperse(rest, elem, [x])
+ [x, ..rest] -> intersperse_loop(rest, elem, [x])
+ }
+}
+
+fn intersperse_loop(list: List(a), separator: a, acc: List(a)) -> List(a) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..rest] -> intersperse_loop(rest, separator, [x, separator, ..acc])
}
}
@@ -1264,7 +1264,7 @@ fn sequences(
// Notice how we have to reverse the accumulator we're growing: since
// we always add items to the head, `growing` is built in the opposite
// sorting order of what it actually is in the original list.
- Ascending -> [do_reverse(growing, []), ..acc]
+ Ascending -> [reverse_loop(growing, []), ..acc]
Descending -> [growing, ..acc]
}
@@ -1285,7 +1285,7 @@ fn sequences(
// be the one we just found.
order.Gt, Ascending | order.Lt, Descending | order.Eq, Descending -> {
let acc = case direction {
- Ascending -> [do_reverse(growing, []), ..acc]
+ Ascending -> [reverse_loop(growing, []), ..acc]
Descending -> [growing, ..acc]
}
case rest {
@@ -1326,7 +1326,7 @@ fn merge_all(
// If we have a single list in descending order, we reverse it to make sure
// it's in ascending order and we're done.
- [sequence], Descending -> do_reverse(sequence, [])
+ [sequence], Descending -> reverse_loop(sequence, [])
// Merging together sequences that are in ascending (descending) order
// reverses their order, so the recursive call will assume to be merging
@@ -1353,12 +1353,12 @@ fn merge_ascending_pairs(
acc: List(List(a)),
) {
case sequences {
- [] -> do_reverse(acc, [])
+ [] -> reverse_loop(acc, [])
// Beware, if we have just one item left we must reverse it: we take
// ascending lists as input and have to return descending ones.
// If we returned it like it is it would be sorted in ascending order.
- [sequence] -> do_reverse([do_reverse(sequence, []), ..acc], [])
+ [sequence] -> reverse_loop([reverse_loop(sequence, []), ..acc], [])
[ascending1, ascending2, ..rest] -> {
let descending = merge_ascendings(ascending1, ascending2, compare, [])
@@ -1375,9 +1375,9 @@ fn merge_descending_pairs(
acc: List(List(a)),
) {
case sequences {
- [] -> do_reverse(acc, [])
+ [] -> reverse_loop(acc, [])
- [sequence] -> do_reverse([do_reverse(sequence, []), ..acc], [])
+ [sequence] -> reverse_loop([reverse_loop(sequence, []), ..acc], [])
[descending1, descending2, ..rest] -> {
let ascending = merge_descendings(descending1, descending2, compare, [])
@@ -1401,7 +1401,7 @@ fn merge_ascendings(
acc: List(a),
) -> List(a) {
case list1, list2 {
- [], list | list, [] -> do_reverse(list, acc)
+ [], list | list, [] -> reverse_loop(list, acc)
[first1, ..rest1], [first2, ..rest2] ->
case compare(first1, first2) {
@@ -1428,7 +1428,7 @@ fn merge_descendings(
acc: List(a),
) -> List(a) {
case list1, list2 {
- [], list | list, [] -> do_reverse(list, acc)
+ [], list | list, [] -> reverse_loop(list, acc)
[first1, ..rest1], [first2, ..rest2] ->
case compare(first1, first2) {
order.Lt -> merge_descendings(list1, rest2, compare, [first2, ..acc])
@@ -1458,21 +1458,14 @@ fn merge_descendings(
/// ```
///
pub fn range(from start: Int, to stop: Int) -> List(Int) {
- tail_recursive_range(start, stop, [])
+ range_loop(start, stop, [])
}
-fn tail_recursive_range(start: Int, stop: Int, acc: List(Int)) -> List(Int) {
+fn range_loop(start: Int, stop: Int, acc: List(Int)) -> List(Int) {
case int.compare(start, stop) {
order.Eq -> [stop, ..acc]
- order.Gt -> tail_recursive_range(start, stop + 1, [stop, ..acc])
- order.Lt -> tail_recursive_range(start, stop - 1, [stop, ..acc])
- }
-}
-
-fn do_repeat(item: a, times: Int, acc: List(a)) -> List(a) {
- case times <= 0 {
- True -> acc
- False -> do_repeat(item, times - 1, [item, ..acc])
+ order.Gt -> range_loop(start, stop + 1, [stop, ..acc])
+ order.Lt -> range_loop(start, stop - 1, [stop, ..acc])
}
}
@@ -1491,17 +1484,13 @@ fn do_repeat(item: a, times: Int, acc: List(a)) -> List(a) {
/// ```
///
pub fn repeat(item a: a, times times: Int) -> List(a) {
- do_repeat(a, times, [])
+ repeat_loop(a, times, [])
}
-fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) {
- case n <= 0 {
- True -> #(reverse(taken), list)
- False ->
- case list {
- [] -> #(reverse(taken), [])
- [first, ..rest] -> do_split(rest, n - 1, [first, ..taken])
- }
+fn repeat_loop(item: a, times: Int, acc: List(a)) -> List(a) {
+ case times <= 0 {
+ True -> acc
+ False -> repeat_loop(item, times - 1, [item, ..acc])
}
}
@@ -1528,20 +1517,16 @@ fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) {
/// ```
///
pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) {
- do_split(list, index, [])
+ split_loop(list, index, [])
}
-fn do_split_while(
- list: List(a),
- f: fn(a) -> Bool,
- acc: List(a),
-) -> #(List(a), List(a)) {
- case list {
- [] -> #(reverse(acc), [])
- [first, ..rest] ->
- case f(first) {
- False -> #(reverse(acc), list)
- _ -> do_split_while(rest, f, [first, ..acc])
+fn split_loop(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) {
+ case n <= 0 {
+ True -> #(reverse(taken), list)
+ False ->
+ case list {
+ [] -> #(reverse(taken), [])
+ [first, ..rest] -> split_loop(rest, n - 1, [first, ..taken])
}
}
}
@@ -1568,7 +1553,22 @@ pub fn split_while(
list list: List(a),
satisfying predicate: fn(a) -> Bool,
) -> #(List(a), List(a)) {
- do_split_while(list, predicate, [])
+ split_while_loop(list, predicate, [])
+}
+
+fn split_while_loop(
+ list: List(a),
+ f: fn(a) -> Bool,
+ acc: List(a),
+) -> #(List(a), List(a)) {
+ case list {
+ [] -> #(reverse(acc), [])
+ [first, ..rest] ->
+ case f(first) {
+ False -> #(reverse(acc), list)
+ _ -> split_while_loop(rest, f, [first, ..acc])
+ }
+ }
}
/// Given a list of 2-element tuples, finds the first tuple that has a given
@@ -1640,17 +1640,6 @@ pub fn key_filter(
})
}
-fn do_pop(haystack, predicate, checked) {
- case haystack {
- [] -> Error(Nil)
- [x, ..rest] ->
- case predicate(x) {
- True -> Ok(#(x, append(reverse(checked), rest)))
- False -> do_pop(rest, predicate, [x, ..checked])
- }
- }
-}
-
/// Removes the first element in a given list for which the predicate function returns `True`.
///
/// Returns `Error(Nil)` if no such element is found.
@@ -1676,20 +1665,16 @@ pub fn pop(
in list: List(a),
one_that is_desired: fn(a) -> Bool,
) -> Result(#(a, List(a)), Nil) {
- do_pop(list, is_desired, [])
+ pop_loop(list, is_desired, [])
}
-fn do_pop_map(
- list: List(a),
- mapper: fn(a) -> Result(b, e),
- checked: List(a),
-) -> Result(#(b, List(a)), Nil) {
- case list {
+fn pop_loop(haystack, predicate, checked) {
+ case haystack {
[] -> Error(Nil)
[x, ..rest] ->
- case mapper(x) {
- Ok(y) -> Ok(#(y, append(reverse(checked), rest)))
- Error(_) -> do_pop_map(rest, mapper, [x, ..checked])
+ case predicate(x) {
+ True -> Ok(#(x, append(reverse(checked), rest)))
+ False -> pop_loop(rest, predicate, [x, ..checked])
}
}
}
@@ -1720,7 +1705,22 @@ pub fn pop_map(
in haystack: List(a),
one_that is_desired: fn(a) -> Result(b, c),
) -> Result(#(b, List(a)), Nil) {
- do_pop_map(haystack, is_desired, [])
+ pop_map_loop(haystack, is_desired, [])
+}
+
+fn pop_map_loop(
+ list: List(a),
+ mapper: fn(a) -> Result(b, e),
+ checked: List(a),
+) -> Result(#(b, List(a)), Nil) {
+ case list {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case mapper(x) {
+ Ok(y) -> Ok(#(y, append(reverse(checked), rest)))
+ Error(_) -> pop_map_loop(rest, mapper, [x, ..checked])
+ }
+ }
}
/// Given a list of 2-element tuples, finds the first tuple that has a given
@@ -1835,17 +1835,6 @@ pub fn try_each(
}
}
-fn do_partition(list, categorise, trues, falses) {
- case list {
- [] -> #(reverse(trues), reverse(falses))
- [first, ..rest] ->
- case categorise(first) {
- True -> do_partition(rest, categorise, [first, ..trues], falses)
- False -> do_partition(rest, categorise, trues, [first, ..falses])
- }
- }
-}
-
/// Partitions a list into a tuple/pair of lists
/// by a given categorisation function.
///
@@ -1862,7 +1851,18 @@ pub fn partition(
list: List(a),
with categorise: fn(a) -> Bool,
) -> #(List(a), List(a)) {
- do_partition(list, categorise, [], [])
+ partition_loop(list, categorise, [], [])
+}
+
+fn partition_loop(list, categorise, trues, falses) {
+ case list {
+ [] -> #(reverse(trues), reverse(falses))
+ [first, ..rest] ->
+ case categorise(first) {
+ True -> partition_loop(rest, categorise, [first, ..trues], falses)
+ False -> partition_loop(rest, categorise, trues, [first, ..falses])
+ }
+ }
}
/// Returns all the permutations of a list.
@@ -1893,15 +1893,6 @@ pub fn permutations(list: List(a)) -> List(List(a)) {
}
}
-fn do_window(acc: List(List(a)), list: List(a), n: Int) -> List(List(a)) {
- let window = take(list, n)
-
- case length(window) == n {
- True -> do_window([window, ..acc], drop(list, 1), n)
- False -> acc
- }
-}
-
/// Returns a list of sliding windows.
///
/// ## Examples
@@ -1919,7 +1910,16 @@ fn do_window(acc: List(List(a)), list: List(a), n: Int) -> List(List(a)) {
pub fn window(list: List(a), by n: Int) -> List(List(a)) {
case n <= 0 {
True -> []
- False -> do_window([], list, n) |> reverse
+ False -> window_loop([], list, n)
+ }
+}
+
+fn window_loop(acc: List(List(a)), list: List(a), n: Int) -> List(List(a)) {
+ let window = take(list, n)
+
+ case length(window) == n {
+ True -> window_loop([window, ..acc], drop(list, 1), n)
+ False -> reverse(acc)
}
}
@@ -1964,21 +1964,6 @@ pub fn drop_while(
}
}
-fn do_take_while(
- list: List(a),
- predicate: fn(a) -> Bool,
- acc: List(a),
-) -> List(a) {
- case list {
- [] -> reverse(acc)
- [first, ..rest] ->
- case predicate(first) {
- True -> do_take_while(rest, predicate, [first, ..acc])
- False -> reverse(acc)
- }
- }
-}
-
/// Takes the first elements in a given list for which the predicate function returns `True`.
///
/// ## Examples
@@ -1992,28 +1977,21 @@ pub fn take_while(
in list: List(a),
satisfying predicate: fn(a) -> Bool,
) -> List(a) {
- do_take_while(list, predicate, [])
+ take_while_loop(list, predicate, [])
}
-fn do_chunk(
+fn take_while_loop(
list: List(a),
- f: fn(a) -> k,
- previous_key: k,
- current_chunk: List(a),
- acc: List(List(a)),
-) -> List(List(a)) {
+ predicate: fn(a) -> Bool,
+ acc: List(a),
+) -> List(a) {
case list {
- [first, ..rest] -> {
- let key = f(first)
- case key == previous_key {
- False -> {
- let new_acc = [reverse(current_chunk), ..acc]
- do_chunk(rest, f, key, [first], new_acc)
- }
- _true -> do_chunk(rest, f, key, [first, ..current_chunk], acc)
+ [] -> reverse(acc)
+ [first, ..rest] ->
+ case predicate(first) {
+ True -> take_while_loop(rest, predicate, [first, ..acc])
+ False -> reverse(acc)
}
- }
- _empty -> reverse([reverse(current_chunk), ..acc])
}
}
@@ -2030,30 +2008,29 @@ fn do_chunk(
pub fn chunk(in list: List(a), by f: fn(a) -> k) -> List(List(a)) {
case list {
[] -> []
- [first, ..rest] -> do_chunk(rest, f, f(first), [first], [])
+ [first, ..rest] -> chunk_loop(rest, f, f(first), [first], [])
}
}
-fn do_sized_chunk(
+fn chunk_loop(
list: List(a),
- count: Int,
- left: Int,
+ f: fn(a) -> k,
+ previous_key: k,
current_chunk: List(a),
acc: List(List(a)),
) -> List(List(a)) {
case list {
- [] ->
- case current_chunk {
- [] -> reverse(acc)
- remaining -> reverse([reverse(remaining), ..acc])
- }
[first, ..rest] -> {
- let chunk = [first, ..current_chunk]
- case left > 1 {
- False -> do_sized_chunk(rest, count, count, [], [reverse(chunk), ..acc])
- True -> do_sized_chunk(rest, count, left - 1, chunk, acc)
+ let key = f(first)
+ case key == previous_key {
+ False -> {
+ let new_acc = [reverse(current_chunk), ..acc]
+ chunk_loop(rest, f, key, [first], new_acc)
+ }
+ _true -> chunk_loop(rest, f, key, [first, ..current_chunk], acc)
}
}
+ _empty -> reverse([reverse(current_chunk), ..acc])
}
}
@@ -2077,7 +2054,31 @@ fn do_sized_chunk(
/// ```
///
pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) {
- do_sized_chunk(list, count, count, [], [])
+ sized_chunk_loop(list, count, count, [], [])
+}
+
+fn sized_chunk_loop(
+ list: List(a),
+ count: Int,
+ left: Int,
+ current_chunk: List(a),
+ acc: List(List(a)),
+) -> List(List(a)) {
+ case list {
+ [] ->
+ case current_chunk {
+ [] -> reverse(acc)
+ remaining -> reverse([reverse(remaining), ..acc])
+ }
+ [first, ..rest] -> {
+ let chunk = [first, ..current_chunk]
+ case left > 1 {
+ True -> sized_chunk_loop(rest, count, left - 1, chunk, acc)
+ False ->
+ sized_chunk_loop(rest, count, count, [], [reverse(chunk), ..acc])
+ }
+ }
+ }
}
/// This function acts similar to fold, but does not take an initial state.
@@ -2107,21 +2108,6 @@ pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) {
}
}
-fn do_scan(
- list: List(a),
- accumulator: acc,
- accumulated: List(acc),
- fun: fn(acc, a) -> acc,
-) -> List(acc) {
- case list {
- [] -> reverse(accumulated)
- [first, ..rest] -> {
- let next = fun(accumulator, first)
- do_scan(rest, next, [next, ..accumulated], fun)
- }
- }
-}
-
/// Similar to `fold`, but yields the state of the accumulator at each stage.
///
/// ## Examples
@@ -2136,7 +2122,22 @@ pub fn scan(
from initial: acc,
with fun: fn(acc, a) -> acc,
) -> List(acc) {
- do_scan(list, initial, [], fun)
+ scan_loop(list, initial, [], fun)
+}
+
+fn scan_loop(
+ list: List(a),
+ accumulator: acc,
+ accumulated: List(acc),
+ fun: fn(acc, a) -> acc,
+) -> List(acc) {
+ case list {
+ [] -> reverse(accumulated)
+ [first, ..rest] -> {
+ let next = fun(accumulator, first)
+ scan_loop(rest, next, [next, ..accumulated], fun)
+ }
+ }
}
/// Returns the last element in the given list.
@@ -2196,16 +2197,6 @@ pub fn combinations(items: List(a), by n: Int) -> List(List(a)) {
}
}
-fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) {
- case items {
- [] -> []
- [first, ..rest] -> {
- let first_combinations = map(rest, with: fn(other) { #(first, other) })
- [first_combinations, ..do_combination_pairs(rest)]
- }
- }
-}
-
/// Return unique pair combinations of elements in the list
///
/// ## Examples
@@ -2216,10 +2207,20 @@ fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) {
/// ```
///
pub fn combination_pairs(items: List(a)) -> List(#(a, a)) {
- do_combination_pairs(items)
+ combination_pairs_loop(items)
|> flatten
}
+fn combination_pairs_loop(items: List(a)) -> List(List(#(a, a))) {
+ case items {
+ [] -> []
+ [first, ..rest] -> {
+ let first_combinations = map(rest, with: fn(other) { #(first, other) })
+ [first_combinations, ..combination_pairs_loop(rest)]
+ }
+ }
+}
+
/// Make a list alternating the elements from the given lists
///
/// ## Examples
@@ -2270,22 +2271,6 @@ pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) {
}
}
-fn do_shuffle_pair_unwrap(list: List(#(Float, a)), acc: List(a)) -> List(a) {
- case list {
- [] -> acc
- [elem_pair, ..enumerable] ->
- do_shuffle_pair_unwrap(enumerable, [elem_pair.1, ..acc])
- }
-}
-
-fn do_shuffle_by_pair_indexes(
- list_of_pairs: List(#(Float, a)),
-) -> List(#(Float, a)) {
- sort(list_of_pairs, fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order {
- float.compare(a_pair.0, b_pair.0)
- })
-}
-
/// Takes a list, randomly sorts all items and returns the shuffled list.
///
/// This function uses `float.random` to decide the order of the elements.
@@ -2301,5 +2286,21 @@ pub fn shuffle(list: List(a)) -> List(a) {
list
|> fold(from: [], with: fn(acc, a) { [#(float.random(), a), ..acc] })
|> do_shuffle_by_pair_indexes()
- |> do_shuffle_pair_unwrap([])
+ |> shuffle_pair_unwrap_loop([])
+}
+
+fn shuffle_pair_unwrap_loop(list: List(#(Float, a)), acc: List(a)) -> List(a) {
+ case list {
+ [] -> acc
+ [elem_pair, ..enumerable] ->
+ shuffle_pair_unwrap_loop(enumerable, [elem_pair.1, ..acc])
+ }
+}
+
+fn do_shuffle_by_pair_indexes(
+ list_of_pairs: List(#(Float, a)),
+) -> List(#(Float, a)) {
+ sort(list_of_pairs, fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order {
+ float.compare(a_pair.0, b_pair.0)
+ })
}
diff --git a/src/gleam/option.gleam b/src/gleam/option.gleam
index 7ada122..585ec2d 100644
--- a/src/gleam/option.gleam
+++ b/src/gleam/option.gleam
@@ -21,21 +21,6 @@ pub type Option(a) {
None
}
-fn do_all(list: List(Option(a)), acc: List(a)) -> Option(List(a)) {
- case list {
- [] -> Some(acc)
- [x, ..rest] -> {
- let accumulate = fn(acc, item) {
- case acc, item {
- Some(values), Some(value) -> Some([value, ..values])
- _, _ -> None
- }
- }
- accumulate(do_all(rest, acc), x)
- }
- }
-}
-
/// Combines a list of `Option`s into a single `Option`.
/// If all elements in the list are `Some` then returns a `Some` holding the list of values.
/// If any element is `None` then returns`None`.
@@ -53,7 +38,22 @@ fn do_all(list: List(Option(a)), acc: List(a)) -> Option(List(a)) {
/// ```
///
pub fn all(list: List(Option(a))) -> Option(List(a)) {
- do_all(list, [])
+ all_loop(list, [])
+}
+
+fn all_loop(list: List(Option(a)), acc: List(a)) -> Option(List(a)) {
+ case list {
+ [] -> Some(acc)
+ [x, ..rest] -> {
+ let accumulate = fn(acc, item) {
+ case acc, item {
+ Some(values), Some(value) -> Some([value, ..values])
+ _, _ -> None
+ }
+ }
+ accumulate(all_loop(rest, acc), x)
+ }
+ }
}
/// Checks whether the `Option` is a `Some` value.
@@ -328,21 +328,6 @@ pub fn lazy_or(first: Option(a), second: fn() -> Option(a)) -> Option(a) {
}
}
-fn do_values(list: List(Option(a)), acc: List(a)) -> List(a) {
- case list {
- [] -> acc
- [first, ..rest] -> {
- let accumulate = fn(acc, item) {
- case item {
- Some(value) -> [value, ..acc]
- None -> acc
- }
- }
- accumulate(do_values(rest, acc), first)
- }
- }
-}
-
/// Given a list of `Option`s,
/// returns only the values inside `Some`.
///
@@ -354,5 +339,20 @@ fn do_values(list: List(Option(a)), acc: List(a)) -> List(a) {
/// ```
///
pub fn values(options: List(Option(a))) -> List(a) {
- do_values(options, [])
+ values_loop(options, [])
+}
+
+fn values_loop(list: List(Option(a)), acc: List(a)) -> List(a) {
+ case list {
+ [] -> acc
+ [first, ..rest] -> {
+ let accumulate = fn(acc, item) {
+ case item {
+ Some(value) -> [value, ..acc]
+ None -> acc
+ }
+ }
+ accumulate(values_loop(rest, acc), first)
+ }
+ }
}
diff --git a/src/gleam/result.gleam b/src/gleam/result.gleam
index 235c347..65cae58 100644
--- a/src/gleam/result.gleam
+++ b/src/gleam/result.gleam
@@ -380,14 +380,14 @@ pub fn all(results: List(Result(a, e))) -> Result(List(a), e) {
/// ```
///
pub fn partition(results: List(Result(a, e))) -> #(List(a), List(e)) {
- do_partition(results, [], [])
+ partition_loop(results, [], [])
}
-fn do_partition(results: List(Result(a, e)), oks: List(a), errors: List(e)) {
+fn partition_loop(results: List(Result(a, e)), oks: List(a), errors: List(e)) {
case results {
[] -> #(oks, errors)
- [Ok(a), ..rest] -> do_partition(rest, [a, ..oks], errors)
- [Error(e), ..rest] -> do_partition(rest, oks, [e, ..errors])
+ [Ok(a), ..rest] -> partition_loop(rest, [a, ..oks], errors)
+ [Error(e), ..rest] -> partition_loop(rest, oks, [e, ..errors])
}
}
diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam
index 14acc23..8a3a57e 100644
--- a/src/gleam/string.gleam
+++ b/src/gleam/string.gleam
@@ -435,13 +435,13 @@ pub fn concat(strings: List(String)) -> String {
/// ```
///
pub fn repeat(string: String, times times: Int) -> String {
- do_repeat(string, times, "")
+ repeat_loop(string, times, "")
}
-fn do_repeat(string: String, times: Int, acc: String) -> String {
+fn repeat_loop(string: String, times: Int, acc: String) -> String {
case times <= 0 {
True -> acc
- False -> do_repeat(string, times - 1, acc <> string)
+ False -> repeat_loop(string, times - 1, acc <> string)
}
}
@@ -646,13 +646,13 @@ fn do_pop_grapheme(string string: String) -> Result(#(String, String), Nil)
///
@external(javascript, "../gleam_stdlib.mjs", "graphemes")
pub fn to_graphemes(string: String) -> List(String) {
- do_to_graphemes(string, [])
+ to_graphemes_loop(string, [])
|> list.reverse
}
-fn do_to_graphemes(string: String, acc: List(String)) -> List(String) {
+fn to_graphemes_loop(string: String, acc: List(String)) -> List(String) {
case pop_grapheme(string) {
- Ok(#(grapheme, rest)) -> do_to_graphemes(rest, [grapheme, ..acc])
+ Ok(#(grapheme, rest)) -> to_graphemes_loop(rest, [grapheme, ..acc])
_ -> acc
}
}
@@ -693,19 +693,18 @@ pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) {
@target(erlang)
fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) {
- do_to_utf_codepoints_impl(<<string:utf8>>, [])
- |> list.reverse
+ to_utf_codepoints_loop(<<string:utf8>>, [])
}
@target(erlang)
-fn do_to_utf_codepoints_impl(
+fn to_utf_codepoints_loop(
bit_array: BitArray,
acc: List(UtfCodepoint),
) -> List(UtfCodepoint) {
case bit_array {
<<first:utf8_codepoint, rest:bytes>> ->
- do_to_utf_codepoints_impl(rest, [first, ..acc])
- _ -> acc
+ to_utf_codepoints_loop(rest, [first, ..acc])
+ _ -> list.reverse(acc)
}
}