427 lines
9.6 KiB
Gleam
427 lines
9.6 KiB
Gleam
import gleam/int
|
|
import gleam/list
|
|
import gleeunit
|
|
import gleeunit/should
|
|
import infiniyield.{Next}
|
|
|
|
pub fn main() {
|
|
gleeunit.main()
|
|
}
|
|
|
|
pub fn step_test() {
|
|
let testcase = fn(subject) {
|
|
let step =
|
|
subject
|
|
|> infiniyield.cycle
|
|
|> infiniyield.step
|
|
|
|
let assert [h, ..t] = subject
|
|
let Next(h2, t2) = step
|
|
h
|
|
|> should.equal(h2)
|
|
t2
|
|
|> infiniyield.take(list.length(t))
|
|
|> should.equal(t)
|
|
}
|
|
|
|
testcase([1])
|
|
testcase([1, 2])
|
|
testcase([1, 2, 3])
|
|
}
|
|
|
|
// a |> cycle |> take(n) == a |> list.take(_, n)
|
|
pub fn take_test() {
|
|
let testcase = fn(n, subject) {
|
|
subject
|
|
|> infiniyield.cycle
|
|
|> infiniyield.take(n)
|
|
|> should.equal(list.take(subject, n))
|
|
}
|
|
|
|
testcase(0, [])
|
|
testcase(-1, [])
|
|
testcase(0, [0])
|
|
testcase(1, [0])
|
|
testcase(-1, [0])
|
|
testcase(0, [0, 1, 2, 3, 4])
|
|
testcase(1, [0, 1, 2, 3, 4])
|
|
testcase(2, [0, 1, 2, 3, 4])
|
|
}
|
|
|
|
pub fn transform_index_test() {
|
|
let f = fn(i, el) { Next(#(i, el), i + 1) }
|
|
|
|
["a", "b", "c", "d"]
|
|
|> infiniyield.cycle
|
|
|> infiniyield.transform(0, f)
|
|
|> infiniyield.take(4)
|
|
|> should.equal([#(0, "a"), #(1, "b"), #(2, "c"), #(3, "d")])
|
|
}
|
|
|
|
pub fn transform_scan_test() {
|
|
let f = fn(acc, el) {
|
|
let result = acc + el
|
|
Next(result, result)
|
|
}
|
|
|
|
[1, 2, 3, 4, 5]
|
|
|> infiniyield.cycle
|
|
|> infiniyield.transform(0, f)
|
|
|> infiniyield.take(5)
|
|
|> should.equal([1, 3, 6, 10, 15])
|
|
}
|
|
|
|
// a |> cycle |> map(f) == a |> list.map(_, f)
|
|
pub fn map_test() {
|
|
let testcase = fn(subject, f) {
|
|
subject
|
|
|> infiniyield.cycle
|
|
|> infiniyield.map(f)
|
|
|> infiniyield.take(list.length(subject))
|
|
|> should.equal(list.map(subject, f))
|
|
}
|
|
|
|
let f = fn(e) { e * 2 }
|
|
testcase([], f)
|
|
testcase([1], f)
|
|
testcase([1, 2, 3], f)
|
|
testcase([1, 2, 3, 4, 5, 6, 7, 8], f)
|
|
}
|
|
|
|
// map2(cycle(a), cycle(b), f) == list.map2(a, b, f)
|
|
pub fn map2_test() {
|
|
let testcase = fn(one, other, f) {
|
|
infiniyield.map2(infiniyield.cycle(one), infiniyield.cycle(other), f)
|
|
|> infiniyield.take(int.min(list.length(one), list.length(other)))
|
|
|> should.equal(list.map2(one, other, f))
|
|
}
|
|
|
|
let f = fn(a, b) { a / b }
|
|
testcase([], [], f)
|
|
testcase([], [2, 10, 3], f)
|
|
testcase([10], [2, 10, 3], f)
|
|
testcase([10, 20], [2, 10, 3], f)
|
|
testcase([10, 20, 30], [2, 10, 3], f)
|
|
testcase([10, 20, 30], [2, 10], f)
|
|
testcase([10, 20, 30], [2], f)
|
|
testcase([10, 20, 30], [], f)
|
|
}
|
|
|
|
pub fn map2_is_lazy_test() {
|
|
let one = infiniyield.cycle([])
|
|
let other = infiniyield.repeatedly(fn() { panic as "unreachable" })
|
|
|
|
infiniyield.map2(one, other, fn(x, y) { x + y })
|
|
|> infiniyield.take(0)
|
|
|> should.equal([])
|
|
}
|
|
|
|
// a |> cycle |> filter(f) == a |> list.filter(_, f)
|
|
pub fn filter_test() {
|
|
let testcase = fn(subject, f) {
|
|
let lst = list.filter(subject, f)
|
|
subject
|
|
|> infiniyield.cycle
|
|
|> infiniyield.filter(f)
|
|
|> infiniyield.take(list.length(lst))
|
|
|> should.equal(lst)
|
|
}
|
|
|
|
let even = fn(x) { x % 2 == 0 }
|
|
testcase([], even)
|
|
testcase([1], even)
|
|
testcase([1, 2], even)
|
|
testcase([1, 2, 3], even)
|
|
testcase([1, 2, 3, 4], even)
|
|
testcase([1, 2, 3, 4, 5], even)
|
|
testcase([1, 2, 3, 4, 5, 6], even)
|
|
}
|
|
|
|
pub fn filter_map_test() {
|
|
let testcase = fn(subject, f) {
|
|
let lst = list.filter_map(subject, f)
|
|
subject
|
|
|> infiniyield.cycle
|
|
|> infiniyield.filter_map(f)
|
|
|> infiniyield.take(list.length(lst))
|
|
|> should.equal(lst)
|
|
}
|
|
|
|
testcase([], int.parse)
|
|
testcase(["1"], int.parse)
|
|
testcase(["1", "2", "3"], int.parse)
|
|
testcase(["1", "a", "b"], int.parse)
|
|
testcase(["l", "2", "3", "a"], int.parse)
|
|
testcase(["1", "c", "3", "a", "b"], int.parse)
|
|
testcase(["1", "20", "ten", "4", "5", "69"], int.parse)
|
|
}
|
|
|
|
pub fn repeat_test() {
|
|
1
|
|
|> infiniyield.repeat
|
|
|> infiniyield.take(5)
|
|
|> should.equal([1, 1, 1, 1, 1])
|
|
}
|
|
|
|
pub fn cycle_test() {
|
|
[1, 2, 3]
|
|
|> infiniyield.cycle
|
|
|> infiniyield.take(9)
|
|
|> should.equal([1, 2, 3, 1, 2, 3, 1, 2, 3])
|
|
}
|
|
|
|
pub fn unfold_test() {
|
|
infiniyield.unfold(2, fn(acc) { infiniyield.Next(acc, acc * 2) })
|
|
|> infiniyield.take(5)
|
|
|> should.equal([2, 4, 8, 16, 32])
|
|
}
|
|
|
|
pub fn incrementing_test() {
|
|
let testcase = fn(a, expected) {
|
|
infiniyield.incrementing(from: a)
|
|
|> infiniyield.take(list.length(expected))
|
|
|> should.equal(expected)
|
|
}
|
|
|
|
testcase(0, [0])
|
|
testcase(1, [1])
|
|
testcase(-1, [-1])
|
|
testcase(0, [0, 1])
|
|
testcase(0, [0, 1, 2, 3, 4, 5])
|
|
testcase(1, [1, 2, 3, 4, 5])
|
|
}
|
|
|
|
pub fn deccrementing_test() {
|
|
let testcase = fn(a, expected) {
|
|
infiniyield.decrementing(from: a)
|
|
|> infiniyield.take(list.length(expected))
|
|
|> should.equal(expected)
|
|
}
|
|
|
|
testcase(0, [0])
|
|
testcase(1, [1])
|
|
testcase(-1, [-1])
|
|
testcase(0, [0, -1])
|
|
testcase(0, [0, -1, -2, -3, -4, -5])
|
|
testcase(1, [1, 0, -1, -2, -3, -4, -5])
|
|
}
|
|
|
|
pub fn drop_test() {
|
|
infiniyield.incrementing(from: 0)
|
|
|> infiniyield.drop(5)
|
|
|> infiniyield.take(6)
|
|
|> should.equal([5, 6, 7, 8, 9, 10])
|
|
}
|
|
|
|
type Cat {
|
|
Cat(id: Int)
|
|
}
|
|
|
|
pub fn find_test() {
|
|
infiniyield.incrementing(from: 0)
|
|
|> infiniyield.find(fn(e) { e == 5 })
|
|
|> should.equal(5)
|
|
|
|
infiniyield.incrementing(from: 0)
|
|
|> infiniyield.find(fn(e) { e > 10 })
|
|
|> should.equal(11)
|
|
|
|
infiniyield.unfold(Cat(id: 1), fn(cat: Cat) {
|
|
infiniyield.Next(cat, Cat(id: cat.id + 1))
|
|
})
|
|
|> infiniyield.find(fn(cat: Cat) { cat.id == 10 })
|
|
|> should.equal(Cat(id: 10))
|
|
}
|
|
|
|
pub fn find_map_test() {
|
|
infiniyield.incrementing(from: 0)
|
|
|> infiniyield.find_map(fn(e) {
|
|
case e == 5 {
|
|
True -> Ok(e)
|
|
False -> Error(Nil)
|
|
}
|
|
})
|
|
|> should.equal(5)
|
|
|
|
infiniyield.incrementing(from: 0)
|
|
|> infiniyield.find_map(fn(e) {
|
|
case e > 10 {
|
|
True -> Ok(e)
|
|
False -> Error(Nil)
|
|
}
|
|
})
|
|
|> should.equal(11)
|
|
|
|
infiniyield.unfold(Cat(id: 1), fn(cat: Cat) {
|
|
infiniyield.Next(cat, Cat(id: cat.id + 1))
|
|
})
|
|
|> infiniyield.find_map(fn(cat: Cat) {
|
|
case cat.id == 10 {
|
|
True -> Ok(cat)
|
|
False -> Error(Nil)
|
|
}
|
|
})
|
|
|> should.equal(Cat(id: 10))
|
|
}
|
|
|
|
pub fn index_test() {
|
|
infiniyield.cycle(["a", "b", "c"])
|
|
|> infiniyield.index
|
|
|> infiniyield.take(3)
|
|
|> should.equal([#("a", 0), #("b", 1), #("c", 2)])
|
|
}
|
|
|
|
pub fn iterate_test() {
|
|
fn(x) { x * 3 }
|
|
|> infiniyield.iterate(from: 1)
|
|
|> infiniyield.take(5)
|
|
|> should.equal([1, 3, 9, 27, 81])
|
|
}
|
|
|
|
pub fn take_while_test() {
|
|
infiniyield.cycle([1, 2, 3, 2, 4])
|
|
|> infiniyield.take_while(satisfying: fn(x) { x < 3 })
|
|
|> should.equal([1, 2])
|
|
}
|
|
|
|
pub fn drop_while_test() {
|
|
infiniyield.cycle([1, 2, 3, 4, 2, 5])
|
|
|> infiniyield.drop_while(satisfying: fn(x) { x < 4 })
|
|
|> infiniyield.take(3)
|
|
|> should.equal([4, 2, 5])
|
|
}
|
|
|
|
pub fn scan_test() {
|
|
infiniyield.cycle([1, 2, 3, 4, 5])
|
|
|> infiniyield.scan(from: 0, with: fn(acc, el) { acc + el })
|
|
|> infiniyield.take(5)
|
|
|> should.equal([1, 3, 6, 10, 15])
|
|
}
|
|
|
|
pub fn zip_test() {
|
|
infiniyield.cycle(["a", "b", "c"])
|
|
|> infiniyield.zip(infiniyield.incrementing(from: 20))
|
|
|> infiniyield.take(3)
|
|
|> should.equal([#("a", 20), #("b", 21), #("c", 22)])
|
|
}
|
|
|
|
pub fn chunk_test() {
|
|
infiniyield.cycle([1, 2, 2, 3, 4, 4, 6, 7, 7])
|
|
|> infiniyield.chunk(by: fn(n) { n % 2 })
|
|
|> infiniyield.take(5)
|
|
|> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7, 1]])
|
|
}
|
|
|
|
pub fn sized_chunk_test() {
|
|
infiniyield.cycle([1, 2, 3, 4, 5, 6])
|
|
|> infiniyield.sized_chunk(into: 2)
|
|
|> infiniyield.take(3)
|
|
|> should.equal([[1, 2], [3, 4], [5, 6]])
|
|
|
|
infiniyield.cycle([1, 2, 3, 4, 5, 6, 7, 8])
|
|
|> infiniyield.sized_chunk(into: 3)
|
|
|> infiniyield.take(3)
|
|
|> should.equal([[1, 2, 3], [4, 5, 6], [7, 8, 1]])
|
|
}
|
|
|
|
pub fn intersperse_test() {
|
|
infiniyield.cycle([1])
|
|
|> infiniyield.intersperse(with: 0)
|
|
|> infiniyield.take(1)
|
|
|> should.equal([1])
|
|
|
|
infiniyield.cycle([1, 2, 3, 4, 5])
|
|
|> infiniyield.intersperse(with: 0)
|
|
|> infiniyield.take(9)
|
|
|> should.equal([1, 0, 2, 0, 3, 0, 4, 0, 5])
|
|
}
|
|
|
|
pub fn interleave_test() {
|
|
infiniyield.cycle([1, 2, 3, 4])
|
|
|> infiniyield.interleave(with: infiniyield.cycle([11, 12, 13, 14]))
|
|
|> infiniyield.take(8)
|
|
|> should.equal([1, 11, 2, 12, 3, 13, 4, 14])
|
|
|
|
infiniyield.cycle([1, 2, 3, 4])
|
|
|> infiniyield.interleave(with: infiniyield.cycle([100]))
|
|
|> infiniyield.take(8)
|
|
|> should.equal([1, 100, 2, 100, 3, 100, 4, 100])
|
|
}
|
|
|
|
// a |> cycle |> fold_until(acc, f) == a |> list.fold_until(acc, f)
|
|
pub fn fold_until_test() {
|
|
let testcase = fn(subject, acc, f) {
|
|
subject
|
|
|> infiniyield.cycle()
|
|
|> infiniyield.fold_until(acc, f)
|
|
|> should.equal(list.fold_until(subject, acc, f))
|
|
}
|
|
|
|
let f = fn(acc, e) {
|
|
case e {
|
|
_ if e < 6 -> list.Continue([e, ..acc])
|
|
_ -> list.Stop(acc)
|
|
}
|
|
}
|
|
testcase([1, 2, 3, 4, 5, 6, 7, 8], [], f)
|
|
|
|
[1, 2, 3, 4, 5, 6, 7, 8]
|
|
|> infiniyield.cycle()
|
|
|> infiniyield.fold_until([], f)
|
|
|> should.equal([5, 4, 3, 2, 1])
|
|
}
|
|
|
|
pub fn first_test() {
|
|
infiniyield.cycle([1, 2, 3])
|
|
|> infiniyield.first
|
|
|> should.equal(1)
|
|
}
|
|
|
|
pub fn at_test() {
|
|
infiniyield.cycle([1, 2, 3, 4])
|
|
|> infiniyield.at(2)
|
|
|> should.equal(3)
|
|
|
|
infiniyield.cycle([1, 2, 3, 4])
|
|
|> infiniyield.at(4)
|
|
|> should.equal(1)
|
|
}
|
|
|
|
pub fn each_test() {
|
|
use it <- infiniyield.each(infiniyield.cycle([1]))
|
|
it
|
|
|> should.equal(1)
|
|
}
|
|
|
|
pub fn yield_test() {
|
|
let items = {
|
|
use <- infiniyield.yield(1)
|
|
use <- infiniyield.yield(2)
|
|
use <- infiniyield.yield(3)
|
|
infiniyield.repeat(0)
|
|
}
|
|
|
|
items
|
|
|> infiniyield.take(6)
|
|
|> should.equal([1, 2, 3, 0, 0, 0])
|
|
}
|
|
|
|
pub fn yield_computes_only_necessary_values_test() {
|
|
let items = {
|
|
use <- infiniyield.yield(1)
|
|
use <- infiniyield.yield(2)
|
|
use <- infiniyield.yield(3)
|
|
panic as "yield computed more values than necessary"
|
|
}
|
|
|
|
items
|
|
|> infiniyield.take(3)
|
|
|> should.equal([1, 2, 3])
|
|
}
|
|
|
|
pub fn prepend_test() {
|
|
infiniyield.cycle([1, 2, 3])
|
|
|> infiniyield.prepend(0)
|
|
|> infiniyield.take(4)
|
|
|> should.equal([0, 1, 2, 3])
|
|
}
|