#!/usr/bin/ruby

#
## Enumerator() tests
#

var e1 = Enumerator({ |cb|
    0..100 -> each { |i|
        i.is_prime && cb(i)
    }
})

var p = (^Inf -> lazy.grep{.is_prime}.first(25))

assert_eq(e1.len, 25)
assert_eq(e1.to_a, e1.first(25) )
assert_eq(e1.to_a, p)
assert_eq(e1.grep{.is_even}, [2])
assert_eq(e1.map {|x| x-1 }, p.map{|x| x-1 })

var e2 = Enumerator({ |cb|
    ^Inf -> each { |i|
        i.is_prime && cb(i)
    }
})

assert_eq(e2.first(25), p)

#
## function test
#

func primes_less_than(n) {
    Enumerator({ |cb|
        for i in range(0, n) {
            cb(i) if i.is_prime
        }
    })
}

var e3 = primes_less_than(100)

assert_eq(e3.to_a, p)
assert_eq(e3.len, p.len)

var e4 = primes_less_than(50)

assert_eq(e4.first(5), [2,3,5,7,11])
assert_eq(e4.len, 15)

#
## Fibonacci
#

var fib = Enumerator({ |yield|
  var (a, b) = (0, 1)
  loop {
    yield(a)
    (a, b) = (b, a + b)
  }
})

assert_eq(fib.first(10), [0, 1, 1, 2, 3, 5, 8, 13, 21, 34])

var palindromes = Enumerator({|f|
    var n = 1
    loop { f(n); n.next_palindrome! }
})

assert_eq(
    palindromes.while { _ < 100 },
    1..100 -> grep { .is_palindrome }
)

do {
    var e = Enumerator({|f| ^Inf -> each {|n| f(n**2 + 1) } })

    assert_eq(
        e.first(10),
        ^10 -> map { _*_ + 1 }
    )

    assert_eq(
        e.first(10, {.is_prime}),
        ^Inf -> lazy.map { _*_ + 1 }.grep{.is_prime}.first(10)
    )
}

say "** Test passed!"
