Moonscript is an interesting imperative weakly-typed programming language with some functional spice.
The Moonscript code compiles into Lua, much more verbose. This provides Moonscript with all Lua features, including coroutines and iterators.
We’re gonna look at three different approaches to implement iterations in Moonscript henceforth.
Standard Lua iteration
The standard iterator consists of three parameters: a step function, the context (usually used as stop condition), and the initial state.
The step function, in turn, must take two parameters, the context (stop condition) and the previous state, returning the next state.
For instance, we’re using the Collatz conjecture.
The Collatz conjecture’s step function might be:
_collatz = (stop, prev) -> return if prev == stop switch prev % 2 when 0 -- even prev / 2 when 1 -- odd prev * 3 + 1
When the sequence reaches the stop condition, it returns nil
(nothing) – the for
calls the step function until it receives nil
back.
Now we can build the iterator function, that receives the step function, the stop condition, and the initial state (that we’re doubling up in order to preserve the parameter):
collatz = => _collatz, 1, @*2
We can use it:
mooni> print x for x in collatz 10 10 5 16 8 4 2 1 mooni>
Closures
The Standard Lua iteration is quite cryptic. A clearer approach is using closures.
Using closures, the Collatz must return the final function, that returns each value by turn, so it needs to hold the context in a free mutable variable:
collatz = => value = @*2 -- free variable -> return if value == 1 switch value % 2 when 0 -- even value /= 2 when 1 -- odd value = value * 3 + 1 value
it works just like before, keeping the value
variable between executions as state.
Coroutine
The most powerful approach Lua can offer is the coroutine. No free variables (closures), only a stateful coroutine yielding results.
There isn’t much fun in coroutined Collatz, so let’s try the Fibonacci number, which has two state variables.
fib = (value using coroutine) -> import wrap, yield from coroutine wrap -> a, b = 0, 1 for _ = 1, value a, b = b, a+b yield a
No magic structures, no free variables, neither (explicitly) side effects, only the good-ol’ fellow for
.
mooni> print x for x in fib 10 1 1 2 3 5 8 13 21 34 55
Top comments (0)