Laziness#
Due to the call-by-need reduction order of bruijn, several operations are lazily evaluated (automagically!).
Infinite lists#
You can use infinite list generators like repeat
or
iterate
to lazily interact with list elements.
:import std/List .
:test (length (take (+3) (repeat (+4)))) ((+3))
:test (take (+5) (iterate ++‣ (+0))) (((+0) : ((+1) : ((+2) : ((+3) : {}(+4))))))
Math#
# power function
:test ((iterate (…⋅… (+2)) (+1)) !! (+3)) ((+8))
# prime numbers
primes nub ((…≠?… (+1)) ∘∘ gcd) (iterate ++‣ (+2)) ⧗ (List Number)
:test (take (+4) primes) ((+2) : ((+3) : ((+5) : {}(+7))))
# fibonacci
fibs head <$> (iterate [~0 : (^0 + ~0)] ((+0) : (+1))) ⧗ (List Number)
:test (take (+4) primes) ((+0) : ((+1) : ((+1) : {}(+2))))
Optimization#
Laziness can (in some cases) produce huge performance boosts. For example:
# 10 seconds
:time (+10) ** (+1000)
# 0.02 seconds
:time ((+10) ** (+1000)) =? (+42)
This works because a ternary number is just a concatenation of trits
which (in this case) gets recursively generated by the pow
function. The eq?
function just throws away the first
argument if it's already clear that the numbers can't be equal (in this
case after the first argument got bigger than (+400)
).