diff options
author | Louis Pilfold <louis@lpil.uk> | 2021-07-26 19:37:38 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2021-07-26 19:37:38 +0100 |
commit | 34d7d8697123eada9fb1d4a36ee1aee2c71a8b9d (patch) | |
tree | 18066f57f29fa8be0f9621ed85e4ae7ab6b711ba | |
parent | 0cc6c9002b781af900bd5da2b7c974c6d3e2a9ab (diff) | |
download | gleam_stdlib-34d7d8697123eada9fb1d4a36ee1aee2c71a8b9d.tar.gz gleam_stdlib-34d7d8697123eada9fb1d4a36ee1aee2c71a8b9d.zip |
Gleam native string padding. Iterator tests
-rw-r--r-- | src/gleam/iterator.gleam | 286 | ||||
-rw-r--r-- | src/gleam/string.gleam | 66 | ||||
-rw-r--r-- | src/gleam_stdlib.js | 8 | ||||
-rw-r--r-- | test/gleam/base_test.gleam | 44 | ||||
-rw-r--r-- | test/gleam/function_test.gleam | 183 | ||||
-rw-r--r-- | test/gleam/iterator_test.gleam | 730 | ||||
-rw-r--r-- | test/gleam/string_test.gleam | 20 |
7 files changed, 668 insertions, 669 deletions
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam index e7405bb..4f8b7ff 100644 --- a/src/gleam/iterator.gleam +++ b/src/gleam/iterator.gleam @@ -922,159 +922,159 @@ if erlang { |> fold(map.new(), group_updater(key)) |> map.map_values(fn(_, group) { list.reverse(group) }) } +} - /// 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. - /// The function is called as f(current_element, accumulator). - /// - /// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator. - /// - /// ## Examples - /// - /// > from_list([]) |> reduce(fn(x, y) { x + y }) - /// Error(Nil) - /// - /// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(x, y) { x + y }) - /// Ok(15) - /// - pub fn reduce( - over iterator: Iterator(e), - with f: fn(e, e) -> e, - ) -> Result(e, Nil) { - case iterator.continuation() { - Stop -> Error(Nil) - Continue(e, next) -> - do_fold(next, f, e) - |> Ok - } +/// 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. +/// The function is called as f(current_element, accumulator). +/// +/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator. +/// +/// ## Examples +/// +/// > from_list([]) |> reduce(fn(x, y) { x + y }) +/// Error(Nil) +/// +/// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(x, y) { x + y }) +/// Ok(15) +/// +pub fn reduce( + over iterator: Iterator(e), + with f: fn(e, e) -> e, +) -> Result(e, Nil) { + case iterator.continuation() { + Stop -> Error(Nil) + Continue(e, next) -> + do_fold(next, f, e) + |> Ok } +} - /// Returns the last element in the given iterator. - /// - /// Returns `Error(Nil)` if the iterator is empty. - /// - /// This function runs in linear time. - /// - /// ## Examples - /// - /// > empty() |> last - /// Error(Nil) - /// - /// > range(1, 10) |> last - /// Ok(9) - /// - pub fn last(iterator: Iterator(element)) -> Result(element, Nil) { - iterator - |> reduce(fn(elem, _) { elem }) - } +/// Returns the last element in the given iterator. +/// +/// Returns `Error(Nil)` if the iterator is empty. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// > empty() |> last +/// Error(Nil) +/// +/// > range(1, 10) |> last +/// Ok(9) +/// +pub fn last(iterator: Iterator(element)) -> Result(element, Nil) { + iterator + |> reduce(fn(elem, _) { elem }) +} - /// Creates an iterator that yields no elements. - /// - /// ## Examples - /// - /// > empty() |> to_list - /// [] - /// - pub fn empty() -> Iterator(element) { - Iterator(stop) - } +/// Creates an iterator that yields no elements. +/// +/// ## Examples +/// +/// > empty() |> to_list +/// [] +/// +pub fn empty() -> Iterator(element) { + Iterator(stop) +} - /// Creates an iterator that yields exactly one element provided by calling the given function. - /// - /// ## Examples - /// - /// > once(fn() { 1 }) |> to_list - /// [1] - /// - pub fn once(f: fn() -> element) -> Iterator(element) { - fn() { Continue(f(), stop) } - |> Iterator - } +/// Creates an iterator that yields exactly one element provided by calling the given function. +/// +/// ## Examples +/// +/// > once(fn() { 1 }) |> to_list +/// [1] +/// +pub fn once(f: fn() -> element) -> Iterator(element) { + fn() { Continue(f(), stop) } + |> Iterator +} - /// Creates an iterator that yields the given element exactly once. - /// - /// ## Examples - /// - /// > single(1) |> to_list - /// [1] - /// - pub fn single(elem: element) -> Iterator(element) { - once(fn() { elem }) - } +/// Creates an iterator that yields the given element exactly once. +/// +/// ## Examples +/// +/// > single(1) |> to_list +/// [1] +/// +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) }) - } +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. - /// - /// ## Examples - /// - /// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list - /// [1, 11, 2, 12, 3, 13, 4, 14] - /// - /// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list - /// [1, 100, 2, 3, 4] - /// - pub fn interleave( - left: Iterator(element), - with right: Iterator(element), - ) -> Iterator(element) { - fn() { do_interleave(left.continuation, right.continuation) } - |> Iterator - } +/// Creates an iterator that alternates between the two given iterators +/// until both have run out. +/// +/// ## Examples +/// +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list +/// [1, 11, 2, 12, 3, 13, 4, 14] +/// +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list +/// [1, 100, 2, 3, 4] +/// +pub fn interleave( + left: Iterator(element), + with right: Iterator(element), +) -> Iterator(element) { + fn() { do_interleave(left.continuation, right.continuation) } + |> Iterator +} - fn do_fold_until( - continuation: fn() -> Action(e), - f: fn(e, acc) -> list.ContinueOrStop(acc), - accumulator: acc, - ) -> acc { - case continuation() { - Stop -> accumulator - Continue(elem, next) -> - case f(elem, accumulator) { - list.Continue(accumulator) -> do_fold_until(next, f, accumulator) - list.Stop(accumulator) -> accumulator - } - } +fn do_fold_until( + continuation: fn() -> Action(e), + f: fn(e, acc) -> list.ContinueOrStop(acc), + accumulator: acc, +) -> acc { + case continuation() { + Stop -> accumulator + Continue(elem, next) -> + case f(elem, accumulator) { + list.Continue(accumulator) -> do_fold_until(next, f, accumulator) + list.Stop(accumulator) -> accumulator + } } +} - /// Like `fold`, `fold_until` reduces an iterator of elements into a single value by calling a given - /// function on each element in turn, but uses a `list.ContinueOrStop` to determine - /// whether or not to keep iterating. - /// - /// If called on an iterator of infinite length then this function will only ever - /// return if the give function returns list.Stop. - /// - /// - /// ## Examples - /// > let f = fn(e, acc) { - /// > case e { - /// > _ if e < 4 -> list.Continue(e + acc) - /// > _ -> list.Stop(acc) - /// > } - /// > } - /// > - /// > [1, 2, 3, 4] - /// > |> from_list - /// > |> iterator.fold_until(from: acc, with: f) - /// 6 - /// - pub fn fold_until( - over iterator: Iterator(e), - from initial: acc, - with f: fn(e, acc) -> list.ContinueOrStop(acc), - ) -> acc { - iterator.continuation - |> do_fold_until(f, initial) - } +/// Like `fold`, `fold_until` reduces an iterator of elements into a single value by calling a given +/// function on each element in turn, but uses a `list.ContinueOrStop` to determine +/// whether or not to keep iterating. +/// +/// If called on an iterator of infinite length then this function will only ever +/// return if the give function returns list.Stop. +/// +/// +/// ## Examples +/// > let f = fn(e, acc) { +/// > case e { +/// > _ if e < 4 -> list.Continue(e + acc) +/// > _ -> list.Stop(acc) +/// > } +/// > } +/// > +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> iterator.fold_until(from: acc, with: f) +/// 6 +/// +pub fn fold_until( + over iterator: Iterator(e), + from initial: acc, + with f: fn(e, acc) -> list.ContinueOrStop(acc), +) -> acc { + iterator.continuation + |> do_fold_until(f, initial) } diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam index 0703dd7..d9d2c63 100644 --- a/src/gleam/string.gleam +++ b/src/gleam/string.gleam @@ -2,7 +2,7 @@ //// text surrounded by `"double quotes"`. import gleam/string_builder -import gleam/iterator +import gleam/iterator.{Iterator} import gleam/list import gleam/order import gleam/result @@ -494,28 +494,13 @@ pub fn join(strings: List(String), with separator: String) -> String { /// > pad_left("121", to: 2, with: ".") /// "121" /// -pub fn pad_left(string: String, to length: Int, with pad_string: String) { - do_pad_left(string, length, pad_string) -} - -if erlang { - type Direction { - Leading - Trailing - Both - } - - fn do_pad_left(string: String, to length: Int, with pad_string: String) { - erl_pad(string, length, Leading, pad_string) - } - - external fn erl_pad(String, Int, Direction, String) -> String = - "gleam_stdlib" "string_pad" -} - -if javascript { - external fn do_pad_left(String, Int, String) -> String = - "../gleam_stdlib.js" "pad_left" +pub fn pad_left(string: String, to desired_length: Int, with pad_string: String) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + padding(to_pad_length, pad_string) + |> iterator.append(iterator.single(string)) + |> iterator.to_list + |> concat } /// Pads a string on the right until it has a given length. @@ -531,19 +516,26 @@ if javascript { /// > pad_right("121", to: 2, with: ".") /// "121" /// -pub fn pad_right(string: String, to length: Int, with pad_string: String) { - do_pad_right(string, length, pad_string) -} - -if erlang { - fn do_pad_right(string: String, to length: Int, with pad_string: String) { - erl_pad(string, length, Trailing, pad_string) - } +pub fn pad_right( + string: String, + to desired_length: Int, + with pad_string: String, +) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + iterator.single(string) + |> iterator.append(padding(to_pad_length, pad_string)) + |> iterator.to_list + |> concat } -if javascript { - external fn do_pad_right(String, Int, String) -> String = - "../gleam_stdlib.js" "pad_right" +fn padding(size: Int, pad_string: String) -> Iterator(String) { + let pad_length = length(pad_string) + let num_pads = size / pad_length + let extra = size % pad_length + iterator.repeat(pad_string) + |> iterator.take(num_pads) + |> iterator.append(iterator.single(slice(pad_string, 0, extra))) } /// Removes whitespace on both sides of a String. @@ -562,6 +554,12 @@ if erlang { erl_trim(string, Both) } + type Direction { + Leading + Trailing + Both + } + external fn erl_trim(String, Direction) -> String = "string" "trim" } diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js index 65dd45c..89908de 100644 --- a/src/gleam_stdlib.js +++ b/src/gleam_stdlib.js @@ -158,11 +158,3 @@ export function trim_left(string) { export function trim_right(string) { return string.trimRight(); } - -export function pad_left(string, length, pad) { - return string.padStart(length, pad); -} - -export function pad_right(string, length, pad) { - return string.padEnd(length, pad); -} diff --git a/test/gleam/base_test.gleam b/test/gleam/base_test.gleam index 80f0024..dd59196 100644 --- a/test/gleam/base_test.gleam +++ b/test/gleam/base_test.gleam @@ -1,31 +1,23 @@ if erlang { import gleam/base - import gleam/bit_string.{BitString} import gleam/io import gleam/list import gleam/should - external fn list_to_binary(List(Int)) -> BitString = - "erlang" "list_to_binary" - pub fn encode64_test() { - [255, 127, 254, 252] - |> list_to_binary() + <<255, 127, 254, 252>> |> base.encode64(True) |> should.equal("/3/+/A==") - [255, 127, 254, 252] - |> list_to_binary() + <<255, 127, 254, 252>> |> base.encode64(False) |> should.equal("/3/+/A") - [0, 0, 0] - |> list_to_binary() + <<0, 0, 0>> |> base.encode64(True) |> should.equal("AAAA") - [] - |> list_to_binary() + <<>> |> base.encode64(True) |> should.equal("") } @@ -33,19 +25,19 @@ if erlang { pub fn decode64_test() { "/3/+/A==" |> base.decode64() - |> should.equal(Ok(list_to_binary([255, 127, 254, 252]))) + |> should.equal(Ok(<<255, 127, 254, 252>>)) "/3/+/A" |> base.decode64() - |> should.equal(Ok(list_to_binary([255, 127, 254, 252]))) + |> should.equal(Ok(<<255, 127, 254, 252>>)) "AAAA" |> base.decode64() - |> should.equal(Ok(list_to_binary([0, 0, 0]))) + |> should.equal(Ok(<<0, 0, 0>>)) "" |> base.decode64() - |> should.equal(Ok(list_to_binary([]))) + |> should.equal(Ok(<<>>)) ")!" |> base.decode64() @@ -53,23 +45,19 @@ if erlang { } pub fn url_encode64_test() { - [255, 127, 254, 252] - |> list_to_binary() + <<255, 127, 254, 252>> |> base.url_encode64(True) |> should.equal("_3_-_A==") - [255, 127, 254, 252] - |> list_to_binary() + <<255, 127, 254, 252>> |> base.url_encode64(False) |> should.equal("_3_-_A") - [0, 0, 0] - |> list_to_binary() + <<0, 0, 0>> |> base.url_encode64(True) |> should.equal("AAAA") - [] - |> list_to_binary() + <<>> |> base.url_encode64(True) |> should.equal("") } @@ -77,19 +65,19 @@ if erlang { pub fn url_decode64_test() { "_3_-_A==" |> base.url_decode64() - |> should.equal(Ok(list_to_binary([255, 127, 254, 252]))) + |> should.equal(Ok(<<255, 127, 254, 252>>)) "_3_-_A" |> base.url_decode64() - |> should.equal(Ok(list_to_binary([255, 127, 254, 252]))) + |> should.equal(Ok(<<255, 127, 254, 252>>)) "AAAA" |> base.url_decode64() - |> should.equal(Ok(list_to_binary([0, 0, 0]))) + |> should.equal(Ok(<<0, 0, 0>>)) "" |> base.url_decode64() - |> should.equal(Ok(list_to_binary([]))) + |> should.equal(Ok(<<>>)) ")!" |> base.url_decode64() diff --git a/test/gleam/function_test.gleam b/test/gleam/function_test.gleam index e4a368c..0b3bd8c 100644 --- a/test/gleam/function_test.gleam +++ b/test/gleam/function_test.gleam @@ -1,112 +1,109 @@ -if erlang { - // TODO: JavaScript - import gleam/should - import gleam/dynamic - import gleam/function - import gleam/int - import gleam/list - import gleam/result - import gleam/string - - pub fn compose_test() { - let add_two = fn(int: Int) { int + 2 } - let add_three = fn(int: Int) { int + 3 } - - let add_five = function.compose(add_two, add_three) - - 1 - |> add_five - |> should.equal(6) - - // Takes a list of ints and returns the head as a string (if there is one, or - // else "0" if there is not) - let head_to_string = - list.head - |> function.compose(result.unwrap(_, 0)) - |> function.compose(int.to_string) - - [1] - |> head_to_string - |> should.equal("1") - - [] - |> head_to_string - |> should.equal("0") - } +import gleam/should +import gleam/dynamic +import gleam/function +import gleam/int +import gleam/list +import gleam/result +import gleam/string + +pub fn compose_test() { + let add_two = fn(int: Int) { int + 2 } + let add_three = fn(int: Int) { int + 3 } + + let add_five = function.compose(add_two, add_three) + + 1 + |> add_five + |> should.equal(6) + + // Takes a list of ints and returns the head as a string (if there is one, or + // else "0" if there is not) + let head_to_string = + list.head + |> function.compose(result.unwrap(_, 0)) + |> function.compose(int.to_string) + + [1] + |> head_to_string + |> should.equal("1") + + [] + |> head_to_string + |> should.equal("0") +} - pub fn curry2_test() { - let fun = fn(a, b) { a + b } - let curried = function.curry2(fun) +pub fn curry2_test() { + let fun = fn(a, b) { a + b } + let curried = function.curry2(fun) - curried(1)(2) - |> should.equal(3) - } + curried(1)(2) + |> should.equal(3) +} - pub fn curry3_test() { - let fun = fn(a, b, c) { a + b + c } - let curried = function.curry3(fun) +pub fn curry3_test() { + let fun = fn(a, b, c) { a + b + c } + let curried = function.curry3(fun) - curried(1)(2)(4) - |> should.equal(7) - } + curried(1)(2)(4) + |> should.equal(7) +} - pub fn curry4_test() { - let fun = fn(a, b, c, d) { a + b + c + d } - let curried = function.curry4(fun) +pub fn curry4_test() { + let fun = fn(a, b, c, d) { a + b + c + d } + let curried = function.curry4(fun) - curried(1)(2)(4)(8) - |> should.equal(15) - } + curried(1)(2)(4)(8) + |> should.equal(15) +} - pub fn curry5_test() { - let fun = fn(a, b, c, d, e) { a + b + c + d + e } - let curried = function.curry5(fun) +pub fn curry5_test() { + let fun = fn(a, b, c, d, e) { a + b + c + d + e } + let curried = function.curry5(fun) - curried(1)(2)(4)(8)(16) - |> should.equal(31) - } + curried(1)(2)(4)(8)(16) + |> should.equal(31) +} - pub fn curry6_test() { - let fun = fn(a, b, c, d, e, f) { a + b + c + d + e + f } - let curried = function.curry6(fun) +pub fn curry6_test() { + let fun = fn(a, b, c, d, e, f) { a + b + c + d + e + f } + let curried = function.curry6(fun) - curried(1)(2)(4)(8)(16)(32) - |> should.equal(63) - } + curried(1)(2)(4)(8)(16)(32) + |> should.equal(63) +} - pub fn flip_test() { - let fun = fn(s: String, i: Int) { - s - |> string.append("String: '", _) - |> string.append("', Int: '") - |> string.append(int.to_string(i)) - |> string.append("'") - } +pub fn flip_test() { + let fun = fn(s: String, i: Int) { + s + |> string.append("String: '", _) + |> string.append("', Int: '") + |> string.append(int.to_string(i)) + |> string.append("'") + } - let flipped_fun = function.flip(fun) + let flipped_fun = function.flip(fun) - fun("Bob", 1) - |> should.equal("String: 'Bob', Int: '1'") + fun("Bob", 1) + |> should.equal("String: 'Bob', Int: '1'") - flipped_fun(2, "Alice") - |> should.equal("String: 'Alice', Int: '2'") - } + flipped_fun(2, "Alice") + |> should.equal("String: 'Alice', Int: '2'") +} - pub fn identity_test() { - 1 - |> function.identity - |> should.equal(1) +pub fn identity_test() { + 1 + |> function.identity + |> should.equal(1) - "" - |> function.identity - |> should.equal("") + "" + |> function.identity + |> should.equal("") - [] - |> function.identity - |> should.equal([]) + [] + |> function.identity + |> should.equal([]) - #(1, 2.0) - |> function.identity - |> should.equal(#(1, 2.0)) - } + #(1, 2.0) + |> function.identity + |> should.equal(#(1, 2.0)) } diff --git a/test/gleam/iterator_test.gleam b/test/gleam/iterator_test.gleam index 50d1c99..8de4251 100644 --- a/test/gleam/iterator_test.gleam +++ b/test/gleam/iterator_test.gleam @@ -1,370 +1,378 @@ +import gleam/should +import gleam/iterator.{Done, Next} +import gleam/list + if erlang { - import gleam/should - import gleam/iterator.{Done, Next} - import gleam/list import gleam/map +} - // a |> from_list |> to_list == a - pub fn to_from_list_test() { - let test = fn(subject) { - subject - |> iterator.from_list - |> iterator.to_list - |> should.equal(subject) - } - - test([]) - test([1]) - test([1, 2]) - test([1, 2, 4, 8]) +// a |> from_list |> to_list == a +pub fn to_from_list_test() { + let test = fn(subject) { + subject + |> iterator.from_list + |> iterator.to_list + |> should.equal(subject) } - pub fn step_test() { - let test = fn(subject) { - let step = - subject - |> iterator.from_list - |> iterator.step - - case subject { - [] -> - step - |> should.equal(Done) - - [h, ..t] -> - step - |> should.equal(Next(h, iterator.from_list(t))) - } - } - - test([]) - test([1]) - test([1, 2]) - test([1, 2, 3]) - } + test([]) + test([1]) + test([1, 2]) + test([1, 2, 4, 8]) +} - // a |> from_list |> take(n) == a |> list.take(_, n) - pub fn take_test() { - let test = fn(n, subject) { +pub fn step_test() { + let test = fn(subject) { + let step = subject |> iterator.from_list - |> iterator.take(n) - |> iterator.to_list - |> should.equal(list.take(subject, n)) + |> iterator.step + + case subject { + [] -> + step + |> should.equal(Done) + + [h, ..t] -> { + assert Next(h2, t2) = step + h + |> should.equal(h2) + t2 + |> iterator.to_list + |> should.equal(t) + } } - - test(0, []) - test(1, []) - test(-1, []) - test(0, [0]) - test(1, [0]) - test(-1, [0]) - test(0, [0, 1, 2, 3, 4]) - test(1, [0, 1, 2, 3, 4]) - test(2, [0, 1, 2, 3, 4]) - test(22, [0, 1, 2, 3, 4]) } - // a |> from_list |> fold(a, f) == a |> list.fold(_, a, f) - pub fn fold_test() { - let test = fn(subject, acc, f) { - subject - |> iterator.from_list - |> iterator.fold(acc, f) - |> should.equal(list.fold(subject, acc, f)) - } - - let f = fn(e, acc) { [e, ..acc] } - test([], [], f) - test([1], [], f) - test([1, 2, 3], [], f) - test([1, 2, 3, 4, 5, 6, 7, 8], [], f) - } + test([]) + test([1]) + test([1, 2]) + test([1, 2, 3]) +} - // a |> from_list |> map(f) |> to_list == a |> list.map(_, f) - pub fn map_test() { - let test = fn(subject, f) { - subject - |> iterator.from_list - |> iterator.map(f) - |> iterator.to_list - |> should.equal(list.map(subject, f)) - } +// a |> from_list |> take(n) == a |> list.take(_, n) +pub fn take_test() { + let test = fn(n, subject) { + subject + |> iterator.from_list + |> iterator.take(n) + |> iterator.to_list + |> should.equal(list.take(subject, n)) + } + + test(0, []) + test(1, []) + test(-1, []) + test(0, [0]) + test(1, [0]) + test(-1, [0]) + test(0, [0, 1, 2, 3, 4]) + test(1, [0, 1, 2, 3, 4]) + test(2, [0, 1, 2, 3, 4]) + test(22, [0, 1, 2, 3, 4]) +} - let f = fn(e) { e * 2 } - test([], f) - test([1], f) - test([1, 2, 3], f) - test([1, 2, 3, 4, 5, 6, 7, 8], f) +// a |> from_list |> fold(a, f) == a |> list.fold(_, a, f) +pub fn fold_test() { + let test = fn(subject, acc, f) { + subject + |> iterator.from_list + |> iterator.fold(acc, f) + |> should.equal(list.fold(subject, acc, f)) } - // a |> from_list |> flat_map(f) |> to_list == - // a |> list.map(f) |> list.map(to_list) |> list.flatten - pub fn flat_map_test() { - let test = fn(subject, f) { - subject - |> iterator.from_list - |> iterator.flat_map(f) - |> iterator.to_list - |> should.equal( - subject - |> list.map(f) - |> list.map(iterator.to_list) - |> list.flatten, - ) - } - - let f = fn(i) { iterator.range(i, i + 2) } + let f = fn(e, acc) { [e, ..acc] } + test([], [], f) + test([1], [], f) + test([1, 2, 3], [], f) + test([1, 2, 3, 4, 5, 6, 7, 8], [], f) +} - test([], f) - test([1], f) - test([1, 2], f) +// a |> from_list |> map(f) |> to_list == a |> list.map(_, f) +pub fn map_test() { + let test = fn(subject, f) { + subject + |> iterator.from_list + |> iterator.map(f) + |> iterator.to_list + |> should.equal(list.map(subject, f)) } - // a |> from_list |> append(from_list(b)) |> to_list == list.flatten([a, b]) - pub fn append_test() { - let test = fn(left, right) { - left - |> iterator.from_list - |> iterator.append(iterator.from_list(right)) - |> iterator.to_list - |> should.equal(list.flatten([left, right])) - } + let f = fn(e) { e * 2 } + test([], f) + test([1], f) + test([1, 2, 3], f) + test([1, 2, 3, 4, 5, 6, 7, 8], f) +} - test([], []) - test([1], [2]) - test([1, 2], [3, 4]) +// a |> from_list |> flat_map(f) |> to_list == +// a |> list.map(f) |> list.map(to_list) |> list.flatten +pub fn flat_map_test() { + let test = fn(subject, f) { + subject + |> iterator.from_list + |> iterator.flat_map(f) + |> iterator.to_list + |> should.equal( + subject + |> list.map(f) + |> list.map(iterator.to_list) + |> list.flatten, + ) } - // a |> list.map(from_list) |> flatten |> to_list == list.flatten(a) - pub fn flatten_test() { - let test = fn(lists) { - lists - |> list.map(iterator.from_list) - |> iterator.from_list - |> iterator.flatten - |> iterator.to_list - |> should.equal(list.flatten(lists)) - } - - test([[], []]) - test([[1], [2]]) - test([[1, 2], [3, 4]]) - } + let f = fn(i) { iterator.range(i, i + 2) } - // a |> from_list |> filter(f) |> to_list == a |> list.filter(_, f) - pub fn filter_test() { - let test = fn(subject, f) { - subject - |> iterator.from_list - |> iterator.filter(f) - |> iterator.to_list - |> should.equal(list.filter(subject, f)) - } + test([], f) + test([1], f) + test([1, 2], f) +} - let even = fn(x) { x % 2 == 0 } - test([], even) - test([1], even) - test([1, 2], even) - test([1, 2, 3], even) - test([1, 2, 3, 4], even) - test([1, 2, 3, 4, 5], even) - test([1, 2, 3, 4, 5, 6], even) +// a |> from_list |> append(from_list(b)) |> to_list == list.flatten([a, b]) +pub fn append_test() { + let test = fn(left, right) { + left + |> iterator.from_list + |> iterator.append(iterator.from_list(right)) + |> iterator.to_list + |> should.equal(list.flatten([left, right])) } - pub fn repeat_test() { - 1 - |> iterator.repeat - |> iterator.take(5) + test([], []) + test([1], [2]) + test([1, 2], [3, 4]) +} + +// a |> list.map(from_list) |> flatten |> to_list == list.flatten(a) +pub fn flatten_test() { + let test = fn(lists) { + lists + |> list.map(iterator.from_list) + |> iterator.from_list + |> iterator.flatten |> iterator.to_list - |> should.equal([1, 1, 1, 1, 1]) + |> should.equal(list.flatten(lists)) } - pub fn cycle_test() { - [1, 2, 3] + test([[], []]) + test([[1], [2]]) + test([[1, 2], [3, 4]]) +} + +// a |> from_list |> filter(f) |> to_list == a |> list.filter(_, f) +pub fn filter_test() { + let test = fn(subject, f) { + subject |> iterator.from_list - |> iterator.cycle - |> iterator.take(9) + |> iterator.filter(f) |> iterator.to_list - |> should.equal([1, 2, 3, 1, 2, 3, 1, 2, 3]) + |> should.equal(list.filter(subject, f)) } - pub fn unfold_test() { - iterator.unfold(2, fn(acc) { iterator.Next(acc, acc * 2) }) - |> iterator.take(5) - |> iterator.to_list - |> should.equal([2, 4, 8, 16, 32]) + let even = fn(x) { x % 2 == 0 } + test([], even) + test([1], even) + test([1, 2], even) + test([1, 2, 3], even) + test([1, 2, 3, 4], even) + test([1, 2, 3, 4, 5], even) + test([1, 2, 3, 4, 5, 6], even) +} - iterator.unfold(2, fn(_) { iterator.Done }) - |> iterator.take(5) - |> iterator.to_list - |> should.equal([]) +pub fn repeat_test() { + 1 + |> iterator.repeat + |> iterator.take(5) + |> iterator.to_list + |> should.equal([1, 1, 1, 1, 1]) +} - fn(n) { - case n { - 0 -> iterator.Done - n -> iterator.Next(element: n, accumulator: n - 1) - } - } - |> iterator.unfold(from: 5) - |> iterator.to_list - |> should.equal([5, 4, 3, 2, 1]) - } +pub fn cycle_test() { + [1, 2, 3] + |> iterator.from_list + |> iterator.cycle + |> iterator.take(9) + |> iterator.to_list + |> should.equal([1, 2, 3, 1, 2, 3, 1, 2, 3]) +} - pub fn range_test() { - let test = fn(a, b, expected) { - iterator.range(a, b) - |> iterator.to_list - |> should.equal(expected) +pub fn unfold_test() { + iterator.unfold(2, fn(acc) { iterator.Next(acc, acc * 2) }) + |> iterator.take(5) + |> iterator.to_list + |> should.equal([2, 4, 8, 16, 32]) + + iterator.unfold(2, fn(_) { iterator.Done }) + |> iterator.take(5) + |> iterator.to_list + |> should.equal([]) + + fn(n) { + case n { + 0 -> iterator.Done + n -> iterator.Next(element: n, accumulator: n - 1) } - - 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]) } + |> iterator.unfold(from: 5) + |> iterator.to_list + |> should.equal([5, 4, 3, 2, 1]) +} - pub fn drop_test() { - iterator.range(0, 10) - |> iterator.drop(5) +pub fn range_test() { + let test = fn(a, b, expected) { + iterator.range(a, b) |> iterator.to_list - |> should.equal([5, 6, 7, 8, 9]) + |> should.equal(expected) } - type Cat { - Cat(id: Int) - } - - pub fn find_test() { - iterator.range(0, 10) - |> iterator.find(fn(e) { e == 5 }) - |> should.equal(Ok(5)) - - iterator.range(0, 10) - |> iterator.find(fn(e) { e > 10 }) - |> should.equal(Error(Nil)) - - iterator.empty() - |> iterator.find(fn(_x) { True }) - |> should.equal(Error(Nil)) + 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]) +} - iterator.unfold( - Cat(id: 1), - fn(cat: Cat) { iterator.Next(cat, Cat(id: cat.id + 1)) }, - ) - |> iterator.find(fn(cat: Cat) { cat.id == 10 }) - |> should.equal(Ok(Cat(id: 10))) - } +pub fn drop_test() { + iterator.range(0, 10) + |> iterator.drop(5) + |> iterator.to_list + |> should.equal([5, 6, 7, 8, 9]) +} - pub fn index_test() { - iterator.from_list(["a", "b", "c"]) - |> iterator.index - |> iterator.to_list - |> should.equal([#(0, "a"), #(1, "b"), #(2, "c")]) - } +type Cat { + Cat(id: Int) +} - pub fn iterate_test() { - fn(x) { x * 3 } - |> iterator.iterate(from: 1) - |> iterator.take(5) - |> iterator.to_list - |> should.equal([1, 3, 9, 27, 81]) - } +pub fn find_test() { + iterator.range(0, 10) + |> iterator.find(fn(e) { e == 5 }) + |> should.equal(Ok(5)) + + iterator.range(0, 10) + |> iterator.find(fn(e) { e > 10 }) + |> should.equal(Error(Nil)) + + iterator.empty() + |> iterator.find(fn(_x) { True }) + |> should.equal(Error(Nil)) + + iterator.unfold( + Cat(id: 1), + fn(cat: Cat) { iterator.Next(cat, Cat(id: cat.id + 1)) }, + ) + |> iterator.find(fn(cat: Cat) { cat.id == 10 }) + |> should.equal(Ok(Cat(id: 10))) +} - pub fn take_while_test() { - iterator.from_list([1, 2, 3, 2, 4]) - |> iterator.take_while(satisfying: fn(x) { x < 3 }) - |> iterator.to_list - |> should.equal([1, 2]) - } +pub fn index_test() { + iterator.from_list(["a", "b", "c"]) + |> iterator.index + |> iterator.to_list + |> should.equal([#(0, "a"), #(1, "b"), #(2, "c")]) +} - pub fn drop_while_test() { - iterator.from_list([1, 2, 3, 4, 2, 5]) - |> iterator.drop_while(satisfying: fn(x) { x < 4 }) - |> iterator.to_list - |> should.equal([4, 2, 5]) - } +pub fn iterate_test() { + fn(x) { x * 3 } + |> iterator.iterate(from: 1) + |> iterator.take(5) + |> iterator.to_list + |> should.equal([1, 3, 9, 27, 81]) +} - pub fn scan_test() { - iterator.from_list([1, 2, 3, 4, 5]) - |> iterator.scan(from: 0, with: fn(el, acc) { acc + el }) - |> iterator.to_list - |> should.equal([1, 3, 6, 10, 15]) - } +pub fn take_while_test() { + iterator.from_list([1, 2, 3, 2, 4]) + |> iterator.take_while(satisfying: fn(x) { x < 3 }) + |> iterator.to_list + |> should.equal([1, 2]) +} - pub fn zip_test() { - iterator.from_list(["a", "b", "c"]) - |> iterator.zip(iterator.range(20, 30)) - |> iterator.to_list - |> should.equal([#("a", 20), #("b", 21), #("c", 22)]) - } +pub fn drop_while_test() { + iterator.from_list([1, 2, 3, 4, 2, 5]) + |> iterator.drop_while(satisfying: fn(x) { x < 4 }) + |> iterator.to_list + |> should.equal([4, 2, 5]) +} - pub fn chunk_test() { - iterator.from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) - |> iterator.chunk(by: fn(n) { n % 2 }) - |> iterator.to_list - |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]]) - } +pub fn scan_test() { + iterator.from_list([1, 2, 3, 4, 5]) + |> iterator.scan(from: 0, with: fn(el, acc) { acc + el }) + |> iterator.to_list + |> should.equal([1, 3, 6, 10, 15]) +} - pub fn sized_chunk_test() { - iterator.from_list([1, 2, 3, 4, 5, 6]) - |> iterator.sized_chunk(into: 2) - |> iterator.to_list - |> should.equal([[1, 2], [3, 4], [5, 6]]) +pub fn zip_test() { + iterator.from_list(["a", "b", "c"]) + |> iterator.zip(iterator.range(20, 30)) + |> iterator.to_list + |> should.equal([#("a", 20), #("b", 21), #("c", 22)]) +} - iterator.from_list([1, 2, 3, 4, 5, 6, 7, 8]) - |> iterator.sized_chunk(into: 3) - |> iterator.to_list - |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]]) - } +pub fn chunk_test() { + iterator.from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) + |> iterator.chunk(by: fn(n) { n % 2 }) + |> iterator.to_list + |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]]) +} - pub fn intersperse_test() { - iterator.empty() - |> iterator.intersperse(with: 0) - |> iterator.to_list - |> should.equal([]) +pub fn sized_chunk_test() { + iterator.from_list([1, 2, 3, 4, 5, 6]) + |> iterator.sized_chunk(into: 2) + |> iterator.to_list + |> should.equal([[1, 2], [3, 4], [5, 6]]) - iterator.from_list([1]) - |> iterator.intersperse(with: 0) - |> iterator.to_list - |> should.equal([1]) + iterator.from_list([1, 2, 3, 4, 5, 6, 7, 8]) + |> iterator.sized_chunk(into: 3) + |> iterator.to_list + |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]]) +} - iterator.from_list([1, 2, 3, 4, 5]) - |> iterator.intersperse(with: 0) - |> iterator.to_list - |> should.equal([1, 0, 2, 0, 3, 0, 4, 0, 5]) - } +pub fn intersperse_test() { + iterator.empty() + |> iterator.intersperse(with: 0) + |> iterator.to_list + |> should.equal([]) + + iterator.from_list([1]) + |> iterator.intersperse(with: 0) + |> iterator.to_list + |> should.equal([1]) + + iterator.from_list([1, 2, 3, 4, 5]) + |> iterator.intersperse(with: 0) + |> iterator.to_list + |> should.equal([1, 0, 2, 0, 3, 0, 4, 0, 5]) +} - pub fn any_test() { - iterator.empty() - |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_false +pub fn any_test() { + iterator.empty() + |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_false - iterator.from_list([1, 2, 5, 7, 9]) - |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_true + iterator.from_list([1, 2, 5, 7, 9]) + |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_true - iterator.from_list([1, 3, 5, 7, 9]) - |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_false - } + iterator.from_list([1, 3, 5, 7, 9]) + |> iterator.any(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_false +} - pub fn all_test() { - iterator.empty() - |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_true +pub fn all_test() { + iterator.empty() + |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_true - iterator.from_list([2, 4, 6, 8]) - |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_true + iterator.from_list([2, 4, 6, 8]) + |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_true - iterator.from_list([2, 4, 5, 8]) - |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) - |> should.be_false - } + iterator.from_list([2, 4, 5, 8]) + |> iterator.all(satisfying: fn(n) { n % 2 == 0 }) + |> should.be_false +} +if erlang { pub fn group_test() { iterator.from_list([1, 2, 3, 4, 5, 6]) |> iterator.group(by: fn(n) { n % 3 }) @@ -380,70 +388,70 @@ if erlang { |> iterator.reduce(with: fn(x, y) { x + y }) |> should.equal(Ok(15)) } +} - pub fn last_test() { - iterator.empty() - |> iterator.last - |> should.equal(Error(Nil)) +pub fn last_test() { + iterator.empty() + |> iterator.last + |> should.equal(Error(Nil)) - iterator.range(1, 10) - |> iterator.last - |> should.equal(Ok(9)) - } + iterator.range(1, 10) + |> iterator.last + |> should.equal(Ok(9)) +} - pub fn empty_test() { - iterator.empty() - |> iterator.to_list - |> should.equal([]) - } +pub fn empty_test() { + iterator.empty() + |> iterator.to_list + |> should.equal([]) +} - pub fn once_test() { - iterator.once(fn() { 1 }) - |> iterator.to_list - |> should.equal([1]) - } +pub fn once_test() { + iterator.once(fn() { 1 }) + |> iterator.to_list + |> should.equal([1]) +} - pub fn single_test() { - iterator.single(1) - |> iterator.to_list - |> should.equal([1]) - } +pub fn single_test() { + iterator.single(1) + |> iterator.to_list + |> should.equal([1]) +} - pub fn interleave_test() { - iterator.from_list([1, 2, 3, 4]) - |> iterator.interleave(with: iterator.from_list([11, 12, 13, 14])) - |> iterator.to_list - |> should.equal([1, 11, 2, 12, 3, 13, 4, 14]) +pub fn interleave_test() { + iterator.from_list([1, 2, 3, 4]) + |> iterator.interleave(with: iterator.from_list([11, 12, 13, 14])) + |> iterator.to_list + |> should.equal([1, 11, 2, 12, 3, 13, 4, 14]) - iterator.from_list([1, 2, 3, 4]) - |> iterator.interleave(with: iterator.from_list([100])) - |> iterator.to_list - |> should.equal([1, 100, 2, 3, 4]) - } + iterator.from_list([1, 2, 3, 4]) + |> iterator.interleave(with: iterator.from_list([100])) + |> iterator.to_list + |> should.equal([1, 100, 2, 3, 4]) +} - // a |> from_list |> fold_until(a, f) == a |> list.fold_until(_, a, f) - pub fn fold_until_test() { - let test = fn(subject, acc, f) { - subject - |> iterator.from_list() - |> iterator.fold_until(acc, f) - |> should.equal(list.fold_until(subject, acc, f)) - } +// a |> from_list |> fold_until(a, f) == a |> list.fold_until(_, a, f) +pub fn fold_until_test() { + let test = fn(subject, acc, f) { + subject + |> iterator.from_list() + |> iterator.fold_until(acc, f) + |> should.equal(list.fold_until(subject, acc, f)) + } - let f = fn(e, acc) { - case e { - _ if e < 6 -> list.Continue([e, ..acc]) - _ -> list.Stop(acc) - } + let f = fn(e, acc) { + case e { + _ if e < 6 -> list.Continue([e, ..acc]) + _ -> list.Stop(acc) } - test([], [], f) - test([1], [], f) - test([1, 2, 3], [], f) - test([1, 2, 3, 4, 5, 6, 7, 8], [], f) - - [1, 2, 3, 4, 5, 6, 7, 8] - |> iterator.from_list() - |> iterator.fold_until([], f) - |> should.equal([5, 4, 3, 2, 1]) } + test([], [], f) + test([1], [], f) + test([1, 2, 3], [], f) + test([1, 2, 3, 4, 5, 6, 7, 8], [], f) + + [1, 2, 3, 4, 5, 6, 7, 8] + |> iterator.from_list() + |> iterator.fold_until([], f) + |> should.equal([5, 4, 3, 2, 1]) } diff --git a/test/gleam/string_test.gleam b/test/gleam/string_test.gleam index 734d369..8ac6d9c 100644 --- a/test/gleam/string_test.gleam +++ b/test/gleam/string_test.gleam @@ -272,8 +272,16 @@ pub fn pad_left_test() { |> should.equal("121") "121" + |> string.pad_left(to: 4, with: "XY") + |> should.equal("X121") + + "121" |> string.pad_left(to: 5, with: "XY") - |> should.equal("XYXY121") + |> should.equal("XY121") + + "121" + |> string.pad_left(to: 6, with: "XY") + |> should.equal("XYX121") } pub fn pad_right_test() { @@ -290,8 +298,16 @@ pub fn pad_right_test() { |> should.equal("121") "121" + |> string.pad_right(to: 4, with: "XY") + |> should.equal("121X") + + "121" |> string.pad_right(to: 5, with: "XY") - |> should.equal("121XYXY") + |> should.equal("121XY") + + "121" + |> string.pad_right(to: 6, with: "XY") + |> should.equal("121XYX") } pub fn pop_grapheme_test() { |