
MoonScript, a programmer friendly language that compiles to Lua - type0
http://moonscript.org/
======
leafo
Hey all, I made MoonScript about 6 years ago.

I used it to build a ton of opensource stuff in addition to the company I
founded. I use it every day and I'm very happy with how it's turned out. I
regret not updating the language more frequently, but I've been busy building
a bunch of stuff in it.

The biggest open source project is a web framework for Open Resty:
[https://github.com/leafo/lapis](https://github.com/leafo/lapis)

It's used for the following open source websites:
[https://github.com/luarocks/luarocks-
site](https://github.com/luarocks/luarocks-site)
[https://github.com/leafo/streak.club](https://github.com/leafo/streak.club)

The company I made, [https://itch.io](https://itch.io) also runs on it. There
are a a ton of extra Lua modules I've made in MoonScript to facilitate it.
Here's a list of my published modules:
[https://luarocks.org/modules/leafo](https://luarocks.org/modules/leafo)

I've also completed Ludum Dare 11 times now, making a game each time in
MoonScript. I've used [https://love2d.org/](https://love2d.org/) as the game
engine. You can find the games on my GitHub:
[https://github.com/leafo?tab=repositories](https://github.com/leafo?tab=repositories)

Feel free to ask any questions

~~~
nawtacawp
I was just looking at love2d, I don't know much about it. My son is 8 and is
very bored with Scratch. A once over the documentation makes me think love2d
might be a good fit for a next step from Scratch. How is the love2d community
and is it active?

~~~
striking
The love2d community is definitely still active, especially on IRC. Some of
the nicest folks I've ever spoken to over the internet.

I can't recommend the language or its community highly enough.

~~~
fb03
A couple of friends just successfully launched a commercial game on
android/ios/steam using love2d, and they're really happy with the results.

I couldn't believe it was made with lua, it runs really smooth.

[http://midipixel.com/warlockstower/](http://midipixel.com/warlockstower/)

~~~
arunaugustine
The love2d source code is in C++. I believe Lua interpreter was embedded as a
scripting mechanism

[https://bitbucket.org/rude/love/src](https://bitbucket.org/rude/love/src)

~~~
praisethemoon
AFAIK, LÖVE integrates LuaJIT.

------
Cyph0n
This is one of @leafo's excellent projects. He has developed a web framework
for MoonScript called Lapis. One of the cool things about Lapis is that it
runs on top of OpenResty, which is a high performance web server for Lua
applications. Lapis is production-ready: it runs his amazing game marketplace,
itch.io.

~~~
leggomylibro
+1 for Lapis - it's fairly barebones, but it's also nice and simple. You can
also code it in Lua, if you feel more comfortable with that.

I was looking into using it to make a site for hosting Love2D games which
would optionally run right in the browser, because lua rocks, but I got
distracted with other things.

------
jdonaldson
On a related topic, Haxe now compiles to Lua as well :
[https://haxe.org/blog/hello-lua/](https://haxe.org/blog/hello-lua/)
(disclosure : I'm the author of the lua target)

Back to moonscript/Lua, I've been super impressed with the YAGNI principals of
the language. I was originally drawn to LuaJIT and its raw speed, but there's
a lot of great things to say about the language and its community.

My goal is to write more Lua for smaller scripting purposes, and use Haxe/Lua
for more complex projects, taking advantage of LuaJIT speed in both cases.

~~~
baldfat
Thank you. The more I use Haxe the more I love it and I have compiled to Luna
and it worked flawlessly. Thank you

~~~
jdonaldson
It makes my day to hear this. Glad it is useful!

------
mtalantikite
Lapis + MoonScript + OpenResty looks like a lot of fun, so I was just starting
to get a local environment running for it and immediately ran into the Lua 5.1
and 5.2+ divergence. For someone who has just been a casual observer of the
Lua ecosystem over the years, can someone talk about the community's feelings
towards that divergence? The OpenResty docs basically state it's not worth the
effort to support anything but Lua 5.1, which at this point is 5 years old and
no longer updated.

From someone on the outside that makes me hesitant to spend much effort
investing in the ecosystem. Are the libraries fragmented across different
versions too? Are there really no plans for an upgrade path, or does everyone
just expect to use 5.1 forever?

~~~
scythe
The reason is that the _ENV feature added in 5.2 would significantly slow down
LuaJIT if it were supported. It's possible that Luac and LuaJIT will re-
converge when Lua 6.0 is released, but arguments about this between Mike Pall
amd Roberto Ierusalimschy have been unproductive so far. Until then, LuaJIT
compiles Lua 5.1 with support for a few 5.2 and 5.3 features, particularly
goto.

~~~
rweichler
You have any references to these arguments between the two gods?

~~~
akavel
Totally not a concrete link, sorry, but - in a video from one of Lua
conferences, I've seen Roberto mention in some polite yet clear way that talks
with Mike which they had had always come to a standstill on something - at
least that's how I recall it. On the other hand, since 2015, Mike was looking
to pass luajit development on to someone else - so with this, situation could
possibly change in the end. But I'm not sure what's the current status of this
search; I seem to recall CloudFlare was reported to be in talks, but I don't
know how it all ended - or if it's still unresolved.

------
weberc2
I understand that people love programming in classes, but I really want
something like a stripped-down ES6. In particular, I want:

1\. Lists and objects/dicts only; objects have no prototypes at all; objects
have no first-class methods, but they can have functions as member variables,
and those functions can close over other data in the object

2\. All function and variable declaration is anonymous (as a consequence of
1); if you want to define a schema for an object, build a function that takes
certain arguments and returns an object with the corresponding structure.

3\. Coroutines/fibers/etc for async things; no promise/callback hell

4\. Type annotations a la Python (not sure how this fits with 2 just yet)

EDIT: I did a bad job of emphasizing this, but syntax is important to me--I
want something that looks like:

    
    
        var foo = {
            x: [1, 2, 3],
            y: (a, b, c) => {
                var sum = a + b + c;
                sum * sum
            },
        }
    

Whether or not you agree that syntax should be a relevant criteria is a
different matter. :)

~~~
RyanSquared
This is basically Lua, excluding type annotations. Lua's form of OOP is very
strange in that methods aren't bound to a parent context, but instead take the
object as a value. For example, `object:method()` is the same as
`object.method(object)`, and `function object:method()` is the same as
`function object.method(self)` - the only difference being calling the
function via `object:method()` is a bit more optimized. There is also a
framework with networking, signals, and other cool features called `cqueues`
which works based off of coroutines.s You might want to check that out too :)

~~~
Cyph0n
And the size of the Lua runtime is nothing short of beautiful. I have yet to
find a use for Lua though, so I'm still waiting for an opportunity to work on
something with it.

~~~
RyanSquared
I find it's used a lot in places you wouldn't expect. I found it used in a car
radio, the modem used in my house, and a few other places. It's lightweight if
you want to use it on embedded systems (for example, NodeMCU) if you're into
that kind of thing.

~~~
wcummings
Iirc its used on some digital cameras as well.

------
vortico
I love the syntax that Coffeescript-like languages are converging to, like
Moonscript, tj's luna
([https://github.com/tj/luna](https://github.com/tj/luna)) and Pogoscript
([http://pogoscript.org/](http://pogoscript.org/)). They fall way on the right
of the "computer code vs. human code" spectrum, which is handy when writing
applications as quickly as possible rather than focusing on fine details like
implementation and performance. It's a shame I don't see it often in the wild,
except for Atom and a few others.

~~~
plexicle
Thankfully, GitHub starting gutting Coffee from Atom a long time ago. There's
still too much in there though.

~~~
vlunkr
While I understand the move to es6 or whatever we're calling it now, a part of
me really misses coffeescript. I found it to be very elegant

~~~
anotherevan
Agreed. Coffeescript was excellent lipstick for the pig that is javascript.

~~~
boomlinde
Not particularly a fan, that analogy is solid. To me, a pig in lipstick seems
somewhat more disturbing than one without.

~~~
anotherevan
I was riffing on an old expression of putting lipstick on a pig.

[https://en.wikipedia.org/wiki/Lipstick_on_a_pig](https://en.wikipedia.org/wiki/Lipstick_on_a_pig)

~~~
boomlinde
I realize that, but the point of the saying is typically that a pig with
lipstick is little or no better than without. My point is that Coffeescript
makes JS _worse_. It just adds an additional layer of complexity when you end
up debugging the same old JS traps. The saying still holds up, because a pig
wearing lipstick could actually be worse than a plain pig.

~~~
anotherevan
Ah, well in that case we are in disagreement. I think Coffeescript is a big
improvement. It produces JS code that conforms to The Good Parts™ without
having to remember to always add that third equals sign or the var keyword to
avoid making a global and other such ridiculous bull-ka-ka.

So you end up not debugging the same old JS traps as much because it is a lot
harder to write them. (You get to debug shiny new JS traps instead, but
there's only so much a good lipstick can do.)

But it's fine if you prefer javascript to coffeescript. Tastes differ. Some
people like bull-ka-ka. _runs away_

------
fasterthanlime
moonscript powers the itch.io indie marketplace - the original announcement
has a quick write-up:
[http://leafo.net/posts/introducing_itchio.html](http://leafo.net/posts/introducing_itchio.html)

After spending years working with Ruby or Java, it was a very nice change of
pace. Lapis (leaf's web framework) is crazy good as well: it's easy to write
fast code, see this article on coroutines: [http://leafo.net/posts/itchio-and-
coroutines.html](http://leafo.net/posts/itchio-and-coroutines.html)

(disclaimer: I work there with Leaf!)

~~~
yowmamasita
Had there been any scaling problems for Lapis-powered apps that you have
worked on?

------
Pxtl
Some of the stuff in Moonscript feels a little overdone and magical, like
parens-less function calls and the syntactically significant whitespace - but
others really feel like they're fixing the gaps in Lua. Moonscript's nice
lambda syntax, ternary operator, default local, implicit return, etc.

But I don't think I really needed the ! operator, for example.

~~~
bakery2k
_fixing the gaps in Lua. Moonscript 's [...] default local_

Roberto Ierusalimschy, the creator of Lua, believes that "Local by default is
wrong." [1].

I don't necessarily agree that local-by-default is _inherently_ wrong, but
every implementation of local-by-default that I've seen has had flaws.

It looks like MoonScript is no different - its scoping rules seem to suffer
from the same "madness" as CoffeeScript [2].

[1] [http://lua-users.org/wiki/LocalByDefault](http://lua-
users.org/wiki/LocalByDefault)

[2] [https://donatstudios.com/CoffeeScript-
Madness](https://donatstudios.com/CoffeeScript-Madness)

~~~
Pxtl
Honestly, it seems like implicit variable declaration is a bad idea. Some
minimal keyword to indicate "this is a new variable in this scope" seems
necessary for sane scoping. It nicely prevents a class of bugs of "oops I made
a typo in that assignment and created a new variable" gets caught.

~~~
abecedarius
Indeed. Is "let x = y+y" so bad? I wonder how much of the resistance owes to
longer words like "local"/"define", or ugly abbrevs like "mut"/"var".

~~~
Pxtl
So what would you use for declaring a variable that won't be assigned to until
lower scope? Like a variable that will be assigned inside a try/catch block
but needs to outlive it so it's declared before the try?

Just

    
    
        let x
    

? That looks weird. Or we're back to "var". Or throwing another keyword at x?

    
    
        let x exist
    

Also weird. I've often dreamed of a nice lua-like math with syntax aimed at
being familiar to a first year college math student, and "let" is an obvious
keyword for variable declaration, but unless you go pure functional you need
to be able to pre-declare variables.

~~~
abecedarius
I'd make try/catch an expression, not a statement, like in Lisp -- it'd still
be "let x = try {...}...". I agree that 'var' for mutable bindings is a
reasonable design. In E it's 'def' for immutable and 'var' for mutable, for
instance; and you can also write just 'def x' and then 'bind x := 42' further
down (with single-assignment semantics). But though that's nice to have, you
can do all right without it; if there was just a single form of definition,
with lexical scope, I'd still prefer it to Lua or Python's designs -- clearer
and less error-prone and still concise.

~~~
Pxtl
I'd use "set" instead of "bind" and be consistent that assignment leverages
the vanilla equality operator (since we're already talking about that for
"let") but yeah, it sounds like you've been thinking about the same stuff I
have.

It sounds like you've been pondering the same problems I have.

In my case it's because I've been working on a rules-engine for scientists and
currently we're using SQL for the rule language and some of the syntactic
warts of SQL are tripping us up.

I keep meaning to learn enough Racket Scheme to experiment with implementing
such a language in macros.

~~~
abecedarius
FWIW, Common Lisp's macro system is relatively simple. I've been meaning to
check out [http://beautifulracket.com/](http://beautifulracket.com/) sometime
to learn about the Racket way.

Maybe Datalog could make a cleaner base for your project? Just a random
thought; bound to be lots more considerations.

Yeah, I have a project right now too where these questions come up --
[https://github.com/darius/squeam](https://github.com/darius/squeam) \--
though it's not really ready for anyone.

------
PatentTroll
I was on a team that used Lua in production on tens of thousands of machines
running 24/7\. The Lua interpreter was the weak link in the system, requiring
at least daily restarts. Squashed so many bugs over the years, and still found
more and more all the time. What I'm saying is, the Lua interpreter itself is
flawed and I can't imagine using it as a runtime if I had the chance to avoid
it. That said, the language was fun and fast and got the job done. The
interpreter could use some work.

~~~
worrydream
This page lists every known bug in the Lua interpreter for the last 14 years,
along with its fix:
[https://www.lua.org/bugs.html](https://www.lua.org/bugs.html)

The average is 8 bugs per year, most fairly obscure. Every Lua release fixes
all known bugs.

Roberto, the chief architect, is kind of fanatical about quality:
[https://www.youtube.com/watch?v=yU5QNKpATxk](https://www.youtube.com/watch?v=yU5QNKpATxk)

I do not believe the interpreter is as flawed as you claim.

~~~
haberman
Agreed. In my experience it is extremely solid code. I haven't come across
anything that I could imagine leading to a need for daily restarts.

And I speak as someone who reported one of the bugs on their bugs page.

------
yev
I find Lua itself very programmer friendly.

~~~
throwaway7645
Agreed, but it looks like it adds a layer of syntax to give you things like
classes without the user having to leverage metatables.

~~~
RyanSquared
That is correct. It's also done dynamically so you don't have any external
dependencies required when transpiling to Lua code.

EDIT: I am not saying this is better - it could certainly be improved or, as
is the case with a project of mine, injected into the runtime as a global
value. It's just good for running MoonScript alongside Lua.

------
partycoder
Adding superlatives to your stuff is, to me, just noise. e.g: "fast",
"simple", "friendly", "lightweight".

I would rather provide conclusive proof, like some side to side comparison of
features to illustrate how idiomatic MoonScript is supposedly friendlier than
Lua.

Personally I think the changes are not necessarily in the right direction:

For example, what if you have a typo in a variable identifier when assigning a
value to a variable? Now you have a new variable. Where to look for the
definition of a variable? It depends on what runs first now. That's not
friendlier. CoffeeScript made the same mistake in the name of simplicity and
it quite frankly doesn't add any value. The time you saved typing "local" will
be now consumed several times debugging and code reviewing... and you will
have to pay more attention during your code reviews.

Then, removing braces and other delimiters. That's not necessarily better
either. Let's remove lane delimiters from streets, traffic signals, stop and
yield signs, and let's make it all implicit based on rules you can follow in
your head. See? doesn't work.

~~~
rweichler
I see it as a toy language. The only person I think would find it useful is
leafo himself since he can edit it however he wants. But everyone else should
stay away from it. Plain Lua is so much better.

~~~
honewatson
Can't agree with that. Having used both Lua and Moonscript quite a bit I think
Moonscript is what most dynamic scripting languages should be. Simple,
succinct and does what you need for a scripting language.

I really enjoy using it.

~~~
rweichler
Care to give an example?

~~~
anonymoushn
The list comprehensions are really great. Most of the time when I'm writing
Lua I can't be bothered to write exactly what Moonscript outputs for a list
comprehension because it's noisy, but it's what I really would write if I
cared about tiny amounts of performance.

~~~
rweichler
Idk. Still not sold. You can do list comprehensions in regular Lua with
something like this:

    
    
        function listcomp(t, f)
            local r = {}
            for k,v in pairs(t) do
                r[k] = v
            end
            return r
        end
    

And then, your Lua code would be like:

    
    
        listcomp({1, 2, 3, 4}, function(k, v)
            return v*2
        end)
    

Which would be the equivalent to this in MoonScript:

    
    
        [v*2 for k,v in pairs({1, 2, 3 ,4})]
    

I dunno. Just seems like a wash to me. And then you think about the extra
compile step to run MoonScript, and the potential performance hits, and I'm
just turned off completely from it.

~~~
shalabhc
There are no potential performance hits. In particular the code generated for
list comprehensions would be faster than your example because there is no
extra function call per item.

------
koolba
"Moonscript is like CoffeeScript for Lua"

That's a very succinct description and from skimming the examples, quite apt.

But what I want is Typescript for Lua, specifically to use with Redis. That
way I can define interfaces for my keys/values and have static checks on their
usage.

~~~
anonfunction
Check out Haxe: [https://haxe.org/blog/hello-
lua/](https://haxe.org/blog/hello-lua/)

------
shalabhc
Another Moonscript project is [https://howl.io](https://howl.io) \- an editor
written almost entirely in Moonscript that runs on LuaJIT.

------
weberc2
How does MoonScript compare to Wren?
[https://github.com/munificent/wren](https://github.com/munificent/wren)

~~~
nextlevelwizard
System.print("Hello world")

It kind a looks like someone wanted to make actual Java-script. To me these
are way too different to even compare, unless you are talking about
performance, but then you are just comparing Lua with wren and there seems to
already be some benchmarking of these on wren.io

------
OriginalPenguin
Can this be used instead of Lua with Redis? Is there an example somewhere of
that?

~~~
bobwaycott
Check out [https://github.com/jondeandres/moon-
redis](https://github.com/jondeandres/moon-redis)

~~~
bpicolo
Pretty sure he means redis scripting
[https://redis.io/commands/eval](https://redis.io/commands/eval)

~~~
OriginalPenguin
Yes, that's what I meant. Thanks!

------
k__
Nice!

We need more programming languages with sane syntax.

------
nirav72
I wonder if this would work with NodeMCU development for esp8266 boards.

------
nilved
Lua is a great language and MoonScript improves on it even further. I used
MoonScript to write a load balancer with OpenResty recently, and World of
Warcraft interface code six years ago. :)

