
MoonScript: Dynamic scripting language that compiles into Lua - dvfjsdhgfv
https://moonscript.org
======
klibertp
No way, that's too soon! I only recently started working on a MoonScript
fork[1][2], I'm not ready for HN! ;) My use case is integration with Awesome
WM, and I hope to bring MS up to modern standards (whatever they happen to be)
in the process.

The current MoonScript is in a really tight spot: the aging codebase doesn't
get updated, there's no one leading the development, and the community has
like 20 members tops. We need people! For both developing the language,
discussing its design, and testing the changes. Feel free to drop by and say
hi on Discord: [https://discord.gg/Y75ZXrD](https://discord.gg/Y75ZXrD)

Also, there's another effort aiming to modernize MS: a compiler written in
C++:
[https://github.com/pigpigyyy/MoonPlus/](https://github.com/pigpigyyy/MoonPlus/)
\- it's new, but it already implements all of the MoonScript language -
definitely worth taking a look at.

[1] It started when I tried to add some FP conveniences to MS:
[https://github.com/leafo/moonscript/issues/407](https://github.com/leafo/moonscript/issues/407)

[2]
[https://github.com/piotrklibert/AwesomeScript](https://github.com/piotrklibert/AwesomeScript)
\- nothing interesting yet, just a few ideas in the issues

~~~
leafo
Thanks for your enthusiasm, but I just wanted to clarify that I'm still
leading the development of the project. I'm happy to see other people's ideas
about how the language could be different, but I'm going to be very
conservative about any accepted changes. I have a lot of code running in
production in MoonScript that I have no plans to rewrite, so I have no plans
to make breaking changes to the language. I feel it has reached a level of
stability with the syntax that I'm mostly happy with. I encourage you to try
out other stuff with your fork though. Hope that explains.

For others, the discord linked above is the official one, so feel free to stop
by.

------
leafo
Hey all, thanks to whoever posted this.

I'm the creator of MoonScript. I code in MoonScript daily, it's an integral
part of many of my projects, including the company I run. It's something I
launched a very long time ago, it's been featured on HN quite a few times now!

I feel a little bad for threads like this: if you look at the github or the
website, it hasn't seen any significant updates in quite some time. The
reality is, though, it's reached a level of stability where I don't need to
worry about it and I can work on using it to build other things. Although I
have many ideas to fundamentally change it, introduce new operators,
paradigms, etc., at the end of the day I value more that is has stayed pretty
consistent. I have 100s of thousands of lines of MoonScript running in
production environments. I'm more interested in refining the tooling &
squashing bugs. I'm considering just bumping the version to 1.0 so people
don't get confused about the viability of using it. If it's something you
think fits your needs then go for it. I will continue to support it
indefinitely because of how integrated it is into many of my projects.

Tell me if you have any questions, thanks!

~~~
fit2rule
Thanks for your hard work leafo! As a huge fan of Lua I'm always bumping into
your contributions to the language and tools ..

Do you have some place where you organise your thoughts and make plans for
Moonscripts' future?

~~~
leafo
Not really, all of my time is going into my company so I'm not really thinking
about big picture stuff with MoonScript.

Some things I would like to eventually finish though:

* JavaScript output backend [https://github.com/leafo/moonscript-javascript-compiler](https://github.com/leafo/moonscript-javascript-compiler)

* Replacing the AST transfomer with something written in tableshape: [https://github.com/leafo/tableshape](https://github.com/leafo/tableshape)

* Experimenting with writing an lpeg alternative that works more like a parser generator, experimented here [https://github.com/leafo/moonparse](https://github.com/leafo/moonparse)

* Formalizing the syntax transformation pipeline (this would be how things like macros could be implemented)

If you have ideas feel free to open issues on the github. I may not be able to
reply immediately but at least they are written down somewhere. Thanks

------
lwb
The guy behind this language is Leaf, who also runs the indie gaming site
[http://itch.io](http://itch.io). His twitter account is
[https://twitter.com/moonscript](https://twitter.com/moonscript). Really cool
guy and he often adds stuff to Itch after people request it on Twitter.
Moonscript is what enables him and one other person to run one of the biggest
indie sites on the web. (Small potatoes compared to Steam/Epic/Blizzard, but
still much more impressive than that you might expect out of a two person
team.)

------
hombre_fatal
After years of people saying things like they wish they had Lua in the browser
instead of "awful" JS, I finally used Lua for the first time writing games
with Pico8
([https://www.lexaloffle.com/pico-8.php](https://www.lexaloffle.com/pico-8.php)).

I found Lua to be so bare-bones and even quirky that I yearned for the
expressiveness of C. I was so unimpressed and miserable working with it that I
wondered if these people in the wild who supposedly love Lua have used another
programming language in the past 15 years.

So, with that said, MoonScript looks essential.

~~~
chii
> I found Lua to be so bare-bones

that's a design feature. Though I do hate the 1-based indexing...

~~~
seibelj
I love lua but the 1-based indexing is the worst decision of all. Just makes
it an odd-duck when bouncing between languages.

~~~
rogual
1-based indexing I can live with. The fact that the "array length" operator
stops at the first nil in the array is what makes Lua unusable for me.

Edit: 1-based indexing I can live with. The fact that the things you create
with {a, b, c} act for the most part like arrays except for the fact that if
they contain nils, the "length" operator is undefined and usually stops at the
first nil, is what makes Lua unusable for me.

~~~
tvb12
That's a really common misconception. If there is a "hole" in the table, the
result from the length operator is undefined. It doesn't always stop at the
first instance of nil. Tracking the table length manually and stashing it in a
key (usually "n") is something you see pretty often.

~~~
crtlaltdel
^this, to me is hard to imagine. i’ve taken it for granted that i didnt need
to track the lengths of my list-like data structures myself. at the least
checking the length of the list of dictionary keys via some builtin.

~~~
lualengths
Best explaination of this I've seen is 'The many lengths of Lua' from Soni L.

[http://lua-users.org/lists/lua-l/2016-09/msg00234.html](http://lua-
users.org/lists/lua-l/2016-09/msg00234.html)

Lua has many lengths. From string lengths to table lengths, from number
lengths to sequence lengths, from sequence lengths to proper sequence lengths.
They are the many lengths of Lua.

The # operator returns string lengths and table lengths. It is the standard
length operator, and it's what you usually use to get the length of an object.

The string.len() function returns string lengths. It typechecks the argument
to make sure it's a string, but otherwise returns the same value as #.

There are various types of table length. Some of them are sequences, some of
them are not. Some have nothing to do with length, but rather with count.

The simplest length is the one provided by ipairs(). It only iterates the
"proper sequence" part of a table. That is, it iterates the set of contiguous
positive integer keys of a table.[1] When in doubt, this is the length you
should rely on. Don't do `for i=1,#t`, but instead use `for i,v in ipairs(t)`.

Another simple length is the one provided by pairs(). This is actually a
count. If for every iteration of pairs() you increment a counter, you'll end
up with the number of keys in a table. It is rarely used, but can be useful
sometimes.

If you want a manual table length, the simplest way to do it is probably to
just use an `n` field. While Lua supports this usage, the standard library
doesn't, so you have to deal with it manually. While the standard library
doesn't natively support the `n` field, some functions, such as table.pack(),
may emit it.

Another length option is the highest key of a table. You can get this length
by combining pairs() and m ath.max(). It can be useful in some niche
applications but it's quite slow, so consider a manual length (see previous
paragraph) instead.

By combining pairs() with type(), you can get the number of non-integer keys
in a table. While this count does exist, I have never seen it used in
practice.

The length operator, #, can also be applied to tables. If your table has a
positive integer key, and there's a smaller possitive integer that is not a
key (i.e. the value associated with it is `nil`), then this shouldn't be used.
When using a table without manual length, this operator is usually faster than
any other method[2], but it does have the aforementioned drawback. This table
length is the only table length that is unspecified for some tables.

Finally, you can also use your own length algorithm. Use this if you want fast
runtime, but the drawbacks of the length operator make it unsuitable for your
use-case.

And these are the many lengths of Lua!

[1] - I'm not sure how many people know this, but this property (stopping on
first `nil`) is actually described in the manual. That is, ipairs() on a table
with "holes" is actually well-defined.

[2] - The Lua manual doesn't guarantee O(log n) time complexity for the length
operator. If you want guaranteed O(log n) runtime, use your own length
algorithm. This means # could have O(n) time complexity (i.e. equivalent to
ipairs()), or even O(m) where m = the number of keys in the table (i.e.
equivalent to pairs() + math.max()).

PS: Sorry for the wall of text.

~~~
grzm
> _" PS: Sorry for the wall of text."_

In the future, it'd be best to just drop a link with a short message as to why
the link is relevant.

------
dang
Last big thread was in 2017:
[https://news.ycombinator.com/item?id=14441492](https://news.ycombinator.com/item?id=14441492)

2012
[https://news.ycombinator.com/item?id=4741331](https://news.ycombinator.com/item?id=4741331)

2011
[https://news.ycombinator.com/item?id=2871748](https://news.ycombinator.com/item?id=2871748)

A bit more from 2011:
[https://news.ycombinator.com/item?id=3342912](https://news.ycombinator.com/item?id=3342912)

Threads about the related web framework:

2019
[https://news.ycombinator.com/item?id=19011356](https://news.ycombinator.com/item?id=19011356)

2014
[https://news.ycombinator.com/item?id=7744777](https://news.ycombinator.com/item?id=7744777)

2013 Show HN:
[https://news.ycombinator.com/item?id=5602917](https://news.ycombinator.com/item?id=5602917)

------
aeosynth
[https://github.com/bakpakin/Fennel](https://github.com/bakpakin/Fennel)

> Fennel is a lisp that compiles to Lua. It aims to be easy to use,
> expressive, and has almost zero overhead compared to handwritten Lua.

~~~
iLemming
Fennel rocks. So clean, so structured, so concise.

------
JNRowe
I _love_ moonscript, it makes lua feel so much more usable for me. Admittedly,
I'm mostly only using it for convenience in configuring apps(such as my
WM¹/video player²/etc).

If you want to see a large-ish example of what you can do with moonscript the
howl editor³ is a great example. It is also a nice extensible editor in its
own right, including a very usable vi mode.

1\. [https://awesomewm.org/](https://awesomewm.org/)

2\. [https://mpv.io/](https://mpv.io/)

3\. [https://howl.io/](https://howl.io/)

~~~
chatmasta
Off topic, but just curious, what makes you choose mpv over VLC?

~~~
JNRowe
No particularly good reason. I have no use for the vlc gui, so mpv is fine for
me. At a push I'd perhaps say the lighter dependency stack is a plus, but if
mpv didn't exist I'd probably install vlc without thinking about it. FWIW, apt
wants me to install 36 new packages for vlc even with --no-install-recommends.

 _edit_ : Or - I guess - some other scriptable media player, as being
extensible is the thing that matters to me. Unless someone magically matches
my quirks with their non-scriptable player ;)

------
meowface
I love everything about MoonScript except for that damn backslash. I think
it's much nicer to use than Lua, but it still bugs me, bikeshedding be damned.
The asymmetry, the fact that no other language (that I know of) uses it for a
similar purpose, just the look of it in between text...

I once came close to trying to create a near-identical fork of the project
which changed the backslash to something else, but I figured it'd be pretty
pointless. I know I'm definitely not the only one who dislikes it, at least.

~~~
MaxBarraclough
You could create a new language that compiles to MoonScript ;-P

------
srean
Creator of Moonscript and Lapis [0] Leafo [
[https://news.ycombinator.com/user?id=leafo](https://news.ycombinator.com/user?id=leafo)
] hangs out here from time to time

[0] [https://leafo.net/lapis/](https://leafo.net/lapis/)

------
s_gourichon
Perhaps an opportunity to mention Nim. Similar time. Nim is unrelated to lua.
Nim syntax is close to Python.

[https://nim-lang.org/](https://nim-lang.org/)

Efficient, expressive, elegant Nim is a statically typed compiled systems
programming language. It combines successful concepts from mature languages
like Python, Ada and Modula.

~~~
JNRowe
Am I the only person who finds "nim is python-y" an odd description? I often
think that even "perl with off-side rule" would make more sense, given the
variety of ways you can express many concepts in nim(TWMTOWTDI) and number of
sigils.

I get that the stdlib is _clearly_ inspired by python¹, and that using a reST-
ish subset for documentation is Python-y. Beyond that surface scratch the
comparison just falls apart, and often seems to end up as a pointless sticking
point when introducing co-workers to nim. You can't even ignore the idea, as
the moment they crack the awesome Nim in Action book or the official docs
they're immediately shown it.

1\. down to being able to just guess module names in a few circumstances.

~~~
beagle3
Python inspired syntax and standard library; Pascal/Ada inspired typing, with
e.g. numeric ranges.

But nothing at all about it is perlish that I can think of.

~~~
JNRowe
> nothing at all about it is perlish that I can think of

Yeah, I could probably have picked a better example or more clearly expressed
my thoughts. I was _attempting_ to make a point about concepts such as the
uniform function call syntax feeling like a perl-style TWMTOWTDI feature to
me.

[The crux was supposed to be about how quickly just seeing the Python
comparison in the docs ends up in a rabbit hole discussion. I didn't help with
my own poor comparison.]

------
lenkite
If you like LISP and Clojure, you will like Fennel [https://fennel-
lang.org/](https://fennel-lang.org/) which also compiles to Lua

------
tfcat
I love the idea of Moonscript but, is this weird to anyone else: \- class
attributes are mutable and shared across all instances!? \- to give an
instance its own state you gotta define attributes in the constructor

In that case, there's OOP modules for raw Lua that work well. I'd prefer to
stick with Lua.

~~~
klibertp
Yes, the class stuff in MS is plain wrong, all of it (except `=>`, maybe). In
my fork, I plan to drop it all. The thing is, the prototypal, copy-on-write
nature of Lua object orientation is _not_ a disability, there's no need to
"fix" it, the model is powerful enough as it is, it just needs to be used
well.

Some years ago I learned Io - another prototype-based language, similar to
Self - and I was amazed at how expressive it is based on a very small set of
core primitives. All the primitives, including async calls in coroutines, are
either built-in in Lua or are trivially implemented with a small code
transformation.

~~~
chatmasta
MoonScript reminds me of CoffeeScript in this regard. Lua and JS are both
prototypical languages, which is a _feature_ , not a bug. Putting some `class`
syntactic sugar around it helps initially, but also causes confusion when it
doesn't act like a traditional OOP class.

~~~
Quenty
Lua isn’t really a prototypical language, it’s a build-your-own-class system.
Metatables help facilitate this. You can do classic OOP if you want.

------
maxpert
So basically a coffee script for Lua. IDK I have mixed feelings for such
transpilers. However I would appreciate one with generics for Go.

~~~
rplnt
There is this for example
[https://github.com/cheekybits/genny](https://github.com/cheekybits/genny)
However, I couldn't justify relying on such tooling for my projects...

------
pansa2
As an embeddable language, does MoonScript’s significant indentation cause any
problems? I imagine it could be difficult to include MoonScript code inline
with C code while preserving the indentation.

Is that so? Or is inline MoonScript code within C files not common?

~~~
leafo
My strategy is typically store MoonScript in separate files, then have build
process that generates Lua and bundles that inside of whatever else. I
wouldn't typically put it in a C file, but I might have the build system
generate a hex encoded string as a header file. (This is actually how I build
the MoonScript source into a single exe for Windows builds)

I recommend doing the MoonScript compile time at program build time to avoid
any unnecessary compilation during runtime.

~~~
pansa2
Thanks. I wonder if this would be any different if the VM executed MoonScript
code directly, rather than first requiring translation to Lua.

I’ve been thinking about the syntax of an embeddable language myself, and have
ruled out significant indentation because of the difficulty of writing such
code inline inside C files. If that’s not a common use case, maybe I should
reconsider...

~~~
leafo
There is no MoonScript VM, if you use the "execute moonscript" function
provided by the moonscript library it internally compiles the moon code to
lua, loads the lua code, then runs the lua code.

This means that MoonScript compiled ahead of time will have the same exact
result as running it on the fly.

------
toastal
I used this playing with a Lapis project years ago. It very much fit the
zeitgeist in the wake CoffeeScript's popularity. Although usable, it feels a
bit dated now and a product of its time. The zeitgeist now requires static
typing.

~~~
mhd
The good thing about playing to fashion is that you just have to wait for
things to cycle.

~~~
marcosdumay
Fashion only cycles on equivalent choices. Some stuff are better or worse than
the alternatives, so they stick either in use or out of it.

Types are one of those things that will stick in use. We will also probably
see a wild diversity of type systems in experimental languages, as there is
very likely one better than everything we use today.

~~~
boomlinde
_> Fashion only cycles on equivalent choices. Some stuff are better or worse
than the alternatives, so they stick either in use or out of it._

Even if that is true, there are potentially a lot of dimensions to consider in
solving the problem of what is better or worse. Some of these dimensions, or
where in that dimension what-is-better falls, take a long time to discover and
are different for different problem spaces. Sometimes you think you've got it
right only to learn that you were wrong much later.

But it isn't true. Fashion is by any indication only loosely concerned with
utility and sometimes settles on downright masochistic flavors-of-the-day.

------
ARandomerDude
The syntax nostalgically reminds me of CoffeeScript, one of my favorite
languages.

~~~
vortico
>The syntax of MoonScript has been heavily inspired by the syntax of
CoffeeScript. MoonScript is CoffeeScript for Lua.

------
xena
I really like MoonScript, it's a shame it's such a dead language.

------
andai
What a beautiful website.

------
kumarvvr
I am waiting for the day a subset of python is available in place of js in the
browser.

That is a language I wouldnt mind to work with on both server and client.

~~~
beagle3
Brython, Transcrypt, RapydScript, Skulpt and PyPyJS provide various tradeoffs
between compatibility and speed.

Nim does server and client as well (compile down to C or JS serverside, JS
clientside), and has Python inspired syntax and standard library.

GWT gives you that for Java; Emscripten and recently WASM gives it to you with
basically anything gcc can compile and then some.

There is no need to wait.

------
wiradikusuma
So this is like CoffeeScript that transpiles to JavaScipt?

Does anyone know if I can use the generated Lua in Redis?

~~~
klibertp
Yes, you can - I use it with Awesome WM, and with OpenResty/Nginx, and it
works fine. MS compiles to pretty straightforward Lua and doesn't include any
code that would make it hard to run as an embedded scripting language.

------
fctorial
> one of the fastest scripting languages

Isn't nodejs faster

~~~
pansa2
Depends what sort of code you’re running. LuaJIT is a tracing JIT - it’s great
for code which runs the same way over-and-over, but has trouble with
unpredictable branches. V8 does a much better job than LuaJIT for things like
a loop containing an if/else with a 50:50 condition.

Overall, the fastest dynamic language JITs are probably V8 and other
JavaScript runtimes - it’s worth noting that none of these use LuaJIT-style
tracing.

~~~
samatman
I wish Mike Pall had stuck around long enough to land hyperblock scheduling :/

[https://github.com/LuaJIT/LuaJIT/issues/37/](https://github.com/LuaJIT/LuaJIT/issues/37/)

That and the quad-color garbage collector would ensure LuaJIT's dominance for
many years to come. The quad-color is well described, and someone might
successfully implement it at some point; I doubt there's another human alive
who could implement hyperblock scheduling. I'd love to be wrong.

~~~
ksec
At least he is still on LuaJiT mailing list.

Does anyone know what he is currently working on ?

