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)