MoonScript, a programmer friendly language that compiles to Lua
moonscript.org
moonscript.org
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
It's used for the following open source websites: https://github.com/luarocks/luarocks-site https://github.com/leafo/streak.club
The company I made, 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
I've also completed Ludum Dare 11 times now, making a game each time in MoonScript. I've used https://love2d.org/ as the game engine. You can find the games on my GitHub: https://github.com/leafo?tab=repositories
Feel free to ask any questions
https://github.com/nesbox/tic.computer/wiki#cartridge-metada...
Plus that file's about 2 MB, so really not surprisingly small.
http://github.com/antirez/load81.gitIn all seriousness, what's it like running a company using a language you built or is there only a couple of other employees? Also, I guess you're not worrying about bitrot as you can maintain it yourself and it doesn't need anything other than lua to run correct? Also, why did you originally pick lua. I'm gonna stop and read the articles now :).
I can't recommend the language or its community highly enough.
I couldn't believe it was made with lua, it runs really smooth.
At our weekly CoderDojo in Zurich, we're using love2d (and processing) as the next step for the kids that over 10 years and who are comfortable with typing.
Both just work!
https://www.meetup.com/Coder-Dojo-Zurich/
Your welcome to join with your kids or as a mentor if you happen to be not too far away...
I like how your HN profile page mentions only MoonScript and not itch.io, though, in that the former is an open source project and the latter is a company :)
I've been following him since the early days of itch.io and the progress he's made with it is astounding.
At 100% scaling, every "i" clearly looks like a "1". It reads "MoonScr1pt" for me: https://i.imgur.com/Ti12E5I.png
If I zoom in or out in the browser the i looks ok again.
Win 10, Chrome 58
> The biggest open source project is a web framework for Open Resty: https://github.com/leafo/lapis
Looks like lapis is ~15K lines. The Howl editor has ~58K lines (including bindings and tests) - making it bigger, technically ;)
Images: http://acpul.tumblr.com/
Code sample: https://github.com/d08ble/acpul-demo/tree/master/dota
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.
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.
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?
> function foo()return function()return a end end
> =foo()()
nil
> a=5
> =foo()()
5
> setfenv(foo,{a=6})
> =foo()()
6 > function foo()
>> local a = _ENV
>> local _ENV = a
>> return {a=function() _ENV = {r=6} end, b = function() return r end}
>> end
> r = 5
> x = foo()
> x.b()
> =x.b()
5
> return x.a()
> return x.b()
6
>
vs > function foo()
return {
a = function() return setfenv(2, {r = 6}) end,
b = function() return r end
}
end
> x = foo()
> = x.a()
bad argument #1 to '?' (invalid level)
stack traceback:
[builtin#11]: at 0x0101faf2a0
[C]: at 0x0101f4ea60
> function foo()
function bar()
setfenv(2, {x=6})
end
bar()
return function() return x end
end
> e = foo()
> =e()
6
I hadn't thought of that...With _ENV, it is fully dynamic, and can be changed "at a distance".
Also:
> function foo()
>> local function bar() return a end
>> setfenv(1,{a=4})
>> return bar
>> end
> a = 9
> =foo()()
9Yes, there are issues with some Lua modules not supporting Lua 5.3, but the major modules support it, and LuaRocks makes installing modules rather easy.
For me personally, the advantages of luajit currently outweigh the desire to upgrade to newer versions of the language.
Regarding Lua 5.1 being old, I haven't really found it to be an issue.. Lua isn't like most scripting languages, it doesn't come with a huge standard library. It's effectively just the language and some primitives. So it ages quite well as is.
The views on the issue amongst the community are divided too. Personally, I have decided most of my new code won't support Lua versions older than 5.3. That means no LuaJIT. If I have to use OpenResty seriously again, I will fork and adapt it to support PUC Lua 5.3. In the meantime, I use Xavante and WSAPI for the little Web code I write in Lua.
Actually, the changes between 5.1, 5.2, 5.3 are super small and smooth compared to what was done between e.g. 4.x and 5.x, where language syntax was changed. Between 5.x versions, with some effort you can make your code portable, if you wish so. (I'd say that's what one would expect when seeing the major digit unchanged in a version string.) There are many libraries which take care to. I'm not 100% sure about this one (i.e. haven't checked), but from the top of my head, based on the author's reputation, I'd blindly say https://github.com/stevedonovan/Penlight should be a nice example of a library portable between 5.x versions.
The proliferation of the 5.1 version is sometimes semi-jokingly seen as a "curse of success" - that it became the first version to really nail it so well, that it spread so wildly, and the newer versions bring small enough changes, that some people find it hard to justify any effort at all to upgrade. But it's also perfectly OK: Lua 5.1 is a great language already, and can simply be seen as a done/completed work.
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. :) -- LuaJIT
local oldG = _G
local newG = setmetatable({}, {
__index = oldG,
})
setmetatable(oldG, {
__index = function(t, k)
return rawget(newG, k)
end,
__newindex = function()
error('attempt to assign global variable')
end,
})
_G = newG
If you want to assign a global variable, `x = 5` will error but `_G.x = 5` won't. foo = {
x: {1, 2, 3},
y: (a, b, c) ->
sum = a + b + c
sum * sum
}If you want implicit returns and really want to disable "fancy features", babel plugins are fairly easy to create – blacklisting certain constructs wouldn't be very difficult, and implicit returns aren't so hard (you can copy my implementation[0] from a JS superset I built called LightScript[1]).
EDIT: bonus of building on babel is that you can get static types for free à la Flow (though typechecking implicit returns may be a pain).
[0] - https://github.com/lightscript/babel-plugin-lightscript/blob...
[1] - http://lightscript.org
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
(disclaimer: I work there with Leaf!)
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
is it possible to get a tattoo with significant whitespace?
But I don't think I really needed the ! operator, for example.
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].
-- will print:
-- 15
-- 0
-- 15
-- 10
y = 0
goodfun = (x) ->
local y
y = 10
y + x
badfun = (x) ->
y = 10
y + x
print(goodfun(5))
print(y)
print(badfun(5))
print(y)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.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.
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 -- though it's not really ready for anyone.
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
I do not believe the interpreter is as flawed as you claim.
And I speak as someone who reported one of the bugs on their bugs page.
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.
Here's an expression to take an integer b and "mod it" into an interval from a to c, given the normal convention from C++ or Python or whatever where intervals are [a, c):
(b-a)%(c-a)+a
And here it is in the lua convention where intervals are [a,c]: (b-a)%(c-a+1)+a
This is a generalization of what you'd do if you got a really big random integer and you wanted to use it to pick from an array. For that, normally you'd write n % array.length
but in Lua you should be careful to write (n % #array) + 1
You can read some other opinion about this here https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E...I've done a lot of programming in one-based languages, and now avoid such languages as much as possible (sometimes have no choice) because nothing seems to naturally fit into that.
you could work in a 0-based index and your n-th step is a_(n-1) and so the final step is a[NUM_STEPS - 1]
in numerical analysis I don't believe i've ever cared that much about slicing. if i wanted to look at a single element in a matrix a_(ij), then I call the matrix a[i,j]. if you had to implement a pivoting algorithm then it's quite useful to call the pivot element a[i,j] and pivot row a[i,:]. i believe most devs would prefer not to have to call elements everytime a[i-1,j-1].
guessing most math guys have worked with both 0 and 1 systems and honestly don't care that much.
For an iterative method, you have an initial value a[0], then take your NUM_STEPS steps, so the final result is a[NUM_STEPS]. If it's one-based, the final result is a[NUM_STEPS+1]. This type of thing trips up my Matlab (one-based) students all the time.
In zero-based linear algebra, the indices i and j start at 0, so the top left entry of a matrix is a[0, 0], the pivot element is a[i, j] and the pivot row is a[i, :]. There isn't any adjustment needed.
Finite differences, Simpson's Rule, etc., seem more natural with zero-based too. x_0 is the left-most value, x_n is the right-most value, and the interval is divided into n pieces.
your matrix example is totally bizarre though. the top left of a matrix A is always A_(1,1). so not sure what a[0,0] means. a 1x1 matrix is always 1 element, which is a[1,1]. the number of elements in a mxn array is m*n.
In maths notation it usually is, yes, but in a zero-based language it's usually a[0, 0] (and I've seen maths and CS papers where it's 0, too). The number of elements in a mxn array is still m*n, but the indices don't go that high. For example, in Python you'd loop through m rows with "for i in range(m)", which will go from 0 to m-1 (actually, you might do "for row in a" and not bother with indices). You hardly ever need to do m-1 manually - if you want the last row it's just a[-1, :].
I'm not saying zero-based is always better, but I haven't seen many situations where one-based is preferable.
A Braun tree is a binary tree that represents a flexible array (indexable everywhere and extendable at both ends). The gist of it is that you take your array index and read it as a binary string that tells you how to go down the tree. If your index is 1, then you're at the right place and you stop. Then you go left/right depending on whether the remainder is 0/1. That is the 1-based interpretation, and it works because 1 is in the first digit while 2 and 3 need the next digit as well.
If you want to use 0-based indices, it doesn't work out as cleanly, because 0 and 1 share the same digit, while 1 and 2 use different digits. So now you have to branch on whether your index is odd or even, and then either (i-1)/2, or (i/2)-1.
It's not a big deal either way, but it turns a simple to visualize data structure into one where you have to think about the indices.
You shouldn't need a branch in a 0-based Braun tree though. (n-1)/2 should be correct all the time.
If you came up in assembly language and C, like me, you tend to think of array indices as offsets, and the first item obviously has an offset of 0. Anything else is absurd. If you came up in any number of environments that view collections like arrays from the standpoint of something like set theory, then the first (1st!) item clearly has an index of 1. What would a zeroeth item even mean?!. See---it's just point of view and familiarity.
I resisted Python for years because I just couldn't get past the clearly fragility and cognitive burden of something so mind-bogglingly stupid as meaningful whitespace. It took me a while to realize this was much more about me than about Python.
You bounce off of these contextual things all the time in Mathematics: Is 1 prime? Do the Whole numbers include 0? Etc., etc. The answer is---depends on who you ask and what you're working on. It can be implicit, especially to a community (like, say, users of a programming language), or it may need to be explicit to avoid confusion "In this house, we obey the Fundamental Theorem of Arithmetic! 1 is not prime!" As long as you get those particular ducks in a row, the problem is mostly just impedance from people mistaking their personal experience for natural law.
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.
In the reference manual, it is quite literally a side by side comparison. MoonScript code is shown to the left, with Lua to the right. MoonScript provides shortened code with minimal overhead compared to how it would be implemented in Lua, and you can see how by viewing the reference manual.
> 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.
This is the same problem with Lua. The best solution that I've found is to have an editor that highlights variables in different colors; once the color has changed (and it should based on if it's similarly named to another variable, so that `asdf` should be a very different color to `asdg`) you know it's a different variable.
> 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.
Except you can still know when a block ends. Your comparison isn't really fair because it's just a cosmetic change. It's as though stop signs were a square instead of an octogon, not if they were just completely removed.
Then, when you remove parenthesis, it's the same as removing a lane delimiter. Matching parenthesis can already be confusing, now try matching invisible parenthesis. That creates more problems than it solves.
If this author wants to borrow aspects of Python, I suggest reading PEP 20: The Zen of Python. "Explicit is better than implicit".
Implicit parenthesis, implicit braces, implicit returns... the more implicit stuff the more work you need to do in your head, and the more you rely on humans. I thought programming was about giving more work to machines, not to humans.
As someone that vastly prefers parenthesis, no, it's not. The block is just bounded by syntactic structure, not by delimiter. It's like replacing lane delimiters with rippled road texture. The delimiter is different and in my opinion inferior, but it's not gone, it's just replaced by some other indicator.
It's more like someone determined that parenthesis were not visually palatable and decided to remove them. Like "hey, that fire extinguisher doesn't look very elegant, let's remove it, or wrap it in wallpaper so nobody can see it".
It's not just whitespace, it's the specific formatting of whitespace. It's just a character, like any other, only defined by it's lack of distinguishing characters. Instead of whitespace, block continuations could be defined by pipes, or angle brackets, or any number of things. They chose wihtespace.
> We trade an unambiguous set of characters --the parentheses-- by whitespace, and make it context sensitive.
Parenthesis are often context sensitive in languages. It's very common for them to handle both code block and object/dict/hash definition. Languages often use '+' for both numeric addition and string concatenation (which in my eyes is often more problematic and less justified than whitespace as a block defining element).
> How is that now more readable? As someone who has had to match these whitespace based parenthesis I can tell you it's not more readable.
"Readable" is subjective. Unless you have experience with it, you would probably find APL more than unreadable, likely impenetrable. Experience can vastly change what one find easy to understand, and easier to learn doesn't necessarily mean better in all respects.
> It's more like someone determined that parenthesis were not visually palatable and decided to remove them.
Or, it actually is that some people prefer it, even if you and I do not, and that's what it is, a preference implemented in the languages they decided to make. It is, to me, subjectively worse, but the key word there is subjectively. There are trade-offs between the benefits and detriments of that style, but we shouldn't fall into the trap of assuming we can make objective claims as to the quality of the choices of languages that prefer structured whitespace as a syntactic element when it's obvious a large percentage of people find it beneficial.
In the end, unless you're being forced to use this language, I'm not sure why it matters what choice they made with regard to this. If you don't like the choices made by this language, don't use it, and your actions will speak for themselves. If enough people feel that way, the language will die out or change. If enough people do like it how it is, it will continue, as it should, because there's no reason we should restrict other people's choices when it comes down to what is by large an aesthetic choice.
Yes. Specific, context sensitive, that requires disambiguation in your head and therefore harder to read.
> We trade an unambiguous set of characters --the parentheses-- by whitespace, and make it context sensitive. Parenthesis are often context sensitive in languages.
Yes, but they're consistent with the mathematical notation everyone has used over their entire life. By the time you pick up a programming language you have most likely used parenthesis for a while.
I am going to create a new language 99% identical to English, where fork means knife, knife means spoon and spoon means fork. Have a happy time translating paragraphs of text involving those 3 objects from English into my language.
> "Readable" is subjective.
Yes. But implicit vs explicit is not subjective. Implicit meaning takes non-zero effort to understand. It works when you the implicit subject is not relevant and you can be abstracted from it, but in this case there is no encapsulation taking place. Therefore, we could objectively say it's less readable. Quod erat demonstrandum.
> Or, it actually is that some people prefer it, even if you and I do not, and that's what it is
Now you have 2 ways of doing the same thing with no added value. Now you have more possible ways of writing down an expression, if you are parsing an expression or refactoring your code with a regex now it's much more complex. If you are writing a coding standard now you will have to make rules for it, and people may not reach agreement on those rules. People may have meeting to discuss which one to use and why, and spend time moving from one style to the other. It's a waste of time.
In 2017 there's still people fighting over tabs vs spaces. Now we add another dimension to it: spaces vs parenthesis. An endless source of bikeshedding.
> In the end, unless you're being forced to use this language
That's not how it works. I have had to use languages that I dislike because that was what was needed in my organization.
As opposed to the natural visual distinctions that we make all the time? Braces are a learned concept. Having something visually offset might be a learned concept, but if it is I bet it's so early it's prior speech developing. People notice visual patterns. An offset bit of text forms a visual pattern. Again, I don't prefer it, but I think you're reaching in your arguments against it.
> I am going to create a new language 99% identical to English, where fork means knife, knife means spoon and spoon means fork. Have a happy time translating paragraphs of text involving those 3 objects from English into my language.
So, exactly the same situation we have with English today, where it changes and slang is used? I'll have to ponder that problem as I kick it in my crib tonight. Or maybe I'll just settle in and watch the boob tube. Surely replacing some words with others isn't and intractable problem?
> Implicit meaning takes non-zero effort to understand.
Whitespace blocks are not always implicit. They may be well defined within the language they are used in (such as in Python). It's no more implicit than < means less than. Both are defined within the language, and < happens to also share meaning with mathematical notation, which makes it easier to grasp initially for those familiar with that, but there's nothing implicit about either as they both use the inclusion of one or more symbols to confer meaning (even if they are space characters), rather than the exclusion of information. You are confusing whitespace for no-space.
> Now you have 2 ways of doing the same thing with no added value.
Of course there is added value. People prefer it. People's preferences have value.
> Now you have more possible ways of writing down an expression, if you are parsing an expression or refactoring your code with a regex now it's much more complex.
That depends on the language and whether there are multiple ways of defining a block. Unless you expect your expression to parse C, Lisp, Python, Smalltalk and Prolog correctly it it's just those pesky Python whitespace blocks that are holding you back. Within Python, space indented blocks are canonical. If you think that is causing too many ways to define how to perform something in different languages, you're probably better off not looking at some of the other languages I listed earlier...
> In 2017 there's still people fighting over tabs vs spaces. Now we add another dimension to it: spaces vs parenthesis. An endless source of bikeshedding.
Not really. Tabs vs spaces is something people that interact in code with each other have to deal with. I doubt Perl and Python developers get upset when they load each other's code, in the other's language, and see the other used spaces instead of parenthesis[1] or vice-versa, because that choice doesn't make sense within those languages. Sure, try to use indentation to define blocks in Perl. It won't do you any good without the parenthesis, because Perl doesn't support that choice.
1: It's obvious at this point we're actually talking about curly-braces, and not parenthesis, right? I'll keep using parenthesis for now for consistency's sake.
But since everything is relative, it doesn't matter anymore. Let's delimit function evaluations and operator precedence with the words "cat" and "dog" from now on. Since everything is a preference, and is relative, it doesn't matter.
However, what you fail to see is that in reality a choice like this involves effort, it has an economic cost, it's not only preference.
Perl uses . or ~ depending on which version you are using. It also uses braces for code blocks and postfixed ifs which prevents errors like:
if (x)
y
z
Instead of: if (x)
y
z
It prides itself to being close to natural language yet still uses braces.It's a pet peeve of mine that languages have promoted + for addition and string concatenation when concatenation and addition are distinct concepts that don't really share a lot in common beyond the surface. To me, in new languages, it signals that someone likely hasn't thought through that issue very clearly, or has and just doesn't care about consistency (which I think it important in a language). Python at least has the excuse of age (even if it's not all that old compared to many others).
One is an aspiration, the other one is a confident claim.
I really enjoy using it.
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. local b
do
local _accum_0 = { }
local _len_0 = 1
for k, v in pairs({
1,
2,
3,
4
}) do
_accum_0[_len_0] = v * 2
_len_0 = _len_0 + 1
end
b = _accum_0
end
It did a pretty good job. Unlike your code, it doesn't have any function calls, and unlike the code I would probably write, it doesn't use the # operator.- default values for function parameters
- list comprehensions
[x * 2 for x in *{1, 2, 3}]
- easier iteration (e.g. `for key, value in pairs obj`)- local is default, not global
- a simple class system if you need it
- `export`, `from` and `import` keywords
- `+=`, `/=`, `*=` etc. operators
- indentation based scope (ok, this is debatable)
I can't think of a single place where plain Lua is actually better. OK maybe `:` is better as a method call operator, but that's it.
function f(a, b, c, d)
a = a or 1
b = b or 2
c = c or 3
d = d or 4
end
> list comprehensionshttps://news.ycombinator.com/item?id=14444215
> local is default, not global
I think this is a con.
> a simple class system if you need it
I also think this is a con, because it limits flexibility.
Here's my class system:
Object = {}
function Object:new()
local self = setmetatable({}, {__index = self})
return self
end
And how to use it: local super = Object
Shape = Object.new(super)
function Shape:new(color)
local self = super.new(self)
self.color = color
return self
end
local super = Shape
RedShape = Object.new(super)
function RedShape:new()
local self = super.new(self, 0xff0000)
return self
end
If I want to add multiple inheritance, or interfaces, it is easy. Because it is just metatables. With MoonScript this is not possible.> `export`, `from` and `import` keywords
Sounds like a con to me. `require` is simple.
> `+=`, `/=`, `*=`
I agree with this one.
function f(a, b, c, d)
a = a or 1
b = b or 2
c = c or 3
d = d or 4
end
Compare with: f = (a=1, b=2, c=3, d=4) -> ...
Also note the latter is correct when you call it as f(false).As for your traffic example: in many circumstances removing lines and signs makes the roads safer (as reported by the guardian). People pay more attention because of increased uncertainty, and aren't driving (or coding) on autopilot. https://www.theguardian.com/commentisfree/2016/feb/04/remova...
Paying attention is precisely what we're paid to do.
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.
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
We need more programming languages with sane syntax.