Luau goes open-source
luau-lang.org
luau-lang.org
> Luau’s type system is structural by default
I think that makes it the second (production-ready) language to have a primarily-structural type system, after TypeScript/Flow(/and Closure to some extent) for JS. I wonder if it will follow in their impressive footsteps or if it will tread new territory.
One of the things that Flow gets right that TypeScript doesn't yet support is switching to nominal type-checking between class instances. In TypeScript you can assign an instance of one class to an instance of another as long as they have compatible fields. Compare:
Flow: https://bit.ly/3jZx4rB
TypeScript doesn't have any understanding of prototypes or prototypal inheritance, which is a big gap considering that it's a fundamental aspect of JS.
I'm really hoping Luau will come to do the right thing with tables and prototypes. Perhaps it already does, but unfortunately there doesn't seem to be a Luau playground to try in the browser.
I was thinking of how you can embed types in structs. You automatically dereference the fields and methods of the components directly from the outside.
# let f x : int = x#foo;;
val f : < foo : int; .. > -> int = <fun>
Actually there is not really a type of "a record that has at least some fields": # type t = < foo : int; .. >;;
Error: A type variable is unbound in this type declaration.
In type < foo : int; .. > as 'a the variable 'a is unbound
Its hidden (row) polymorphism, it's not subtyping but type abstraction. We're implicitely quantifying over the actual type: # type 'a t = < foo : int; .. > as 'a;;
type 'a t = 'a constraint 'a = < foo : int; .. >
For the record (ha!), for people who don't know ocaml here are "structural sum types", or polymorphic variants as we call them. # let x = `Bar;;
val x : [> `Bar ] = `Bar
above: type of `Bar is a sum containing "at least" (polymorphic) `Bar # type int_opt = [ `Some of int | `None ];;
type int_opt = [ `None | `Some of int ]
above: some "exact" nameless sum type, with arguments # type 'a t = [< `Foo | `Bar ] as 'a;;
type 'a t = 'a constraint 'a = [< `Bar | `Foo ]
above: polymorphic type of sums which contain at most these two constructors.refs:
https://dev.realworldocaml.org/objects.html
https://dev.realworldocaml.org/variants.html#polymorphic-var...
Fun fact: If you add a private field to a class it'll behave nominally in TS. This is because private fields kinda require nominal relations to function. So, in a way, it does support "switching" to nominal type checking for classes - the opt in is simply per-class.
class CovariantFoo<T> {
private phantom!: T
}
class ContravariantFoo<T> {
private phantom!: (_: T) => void
}
class InvariantFoo<T> {
private phantom!: (_: T) => T
}
(inspired by Rust [0])[0] https://kotlinlang.org/docs/generics.html#variance
[1] https://kotlinlang.org/docs/generics.html#declaration-site-v...
https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-ki...
We'd like to afford the same kind of ideas for native Luau code, but we're not there yet.
To be fair to Typescript, it's an insane fundamental aspect of JS.
A regular MOVE is sort-of structural. It moves field i of the source to field i of the destination. Source and destination need not be of the same type, though.
MOVE CORRESPONDING is nominal. It moves field Foo of the source to field Foo of the destination (leaving fields that do not have corresponding items alone)
In both cases, data may be converted, for example from alphabetic to alphanumeric.
I assume we are talking about a static type system here? Many common "scripting" languages are structurally typed - what Python calls duck typing.
They're the biggest PITA right now as designed in PUC-Rio, and I see that while you've improved upon __eq, other metamethods are still lacking.
In PUC-Rio, boolean equality operators FORCE a boolean result, regardless of what you return. Ideally they would allow returning any result type, which then can be coerced to boolean later (e.g. by an `if` statement), just like the arithmetic operators do.
Further, `__neq`, `__ge` and `__gt` do not exist. They should.
The lack of a proper metamethod design means that binding to e.g. Kiwi[0] is impossible without some incredibly fugly hacks. It has been a long-standing annoyance with Lua in an otherwise beautiful little scripting language (that I use frequently).
This looks quite nice - lots of attempts in this space but nothing that attempts to match Lua to this degree.
False. You need all operators because for database NULL-alike logic you cannot infer results from one half of operators.
NULL < NULL == false
NULL > NULL == falsehttp://sqlfiddle.com/#!4/d8fff5/14/0
func_a() > func_b()
I expect left-to-right execution order. Not that it should matter in a good code, but anyway.I don't know what this fork changes, but I love how many game engines will take lua and expand it to fit their exact needs like this.
Very few scripting languages make it as easy to do as lua.
This is an interesting related project:
It compiles down to lua, and really beefs everything up. Interface is super nice too. You just put `require "moonscript"` at the top of the file and you're done, now just write your code in moon script.
Makes me wonder if there's anything useful to "upstream" to vanilla lua here, or if the VM deviated too far.
* I'm tangentially aware of some RFCs to deprecate metatable related methods (setmetatable, getmetatable, rawset, etc), which may have an impact.
In particular, I am pretty sure that it won't do the right thing when it encounters the extra syntax we've added to Luau. So far, that's an if-else expression and a continue keyword. Transpiling those accurately will take a bit of work.
Here's a whole list of languages that compile to Lua (many of them statically typed): https://github.com/hengestone/lua-languages
At first I was a bit surprised by this, given that they have much better type information, but they forget to mention until further on that Luau doesn't use JIT/AOT optimizations (yet). Still, it's as good an excuse as any to bring out this quote again:
“LuaJIT is much faster than all of the other languages, including Wren, because Mike Pall is a robot from the future”
- Robert Nystrom
Just curious, appreciate any context you can provide!
There's no manifests, no class definitions, no anything really. It's as simple as calling lua_newstate to create a state, calling lua_pushcfunction to register some functions that expose your desired engine functionality, and calling lua_loadstring with a script to run.
That means you can use Lua in your engine for something as simple as a CLI interface that just exposes a couple dozen functions, and it's still worth it. Where with any other scripting language you'd have to be doing a lot more with it to make the setup cost worthwhile.
Having LuaJIT available if you end up wanting to do more with it later is the icing on the cake.
The main reason is momentum - Lua has been the de-facto standard embeddable language for at least 15 years. For example, it's used in World of Warcraft which was released in 2004.
Another reason is the quality of the implementation - Lua has very few bugs [0], whereas Shopify tried to embed mruby and had to give up because it had too many security holes [1].
Finally, Lua is a complete language in itself, with a guidebook, reference manual and so on. Mruby (and MicroPython) are less well-known. Plenty of people know Ruby or Python, but if you use the smaller implementations, you never know when your code might hit a language feature that they don't support.
[0] https://www.lua.org/bugs.html [1] https://brandur.org/fragments/shopify-mruby
I mean, we're mainly talking about games here. Choosing performance over developer comfort is the default.
Keep in mind that what we see on the internet is a vocal publicly part. Some important domains are not publicly represented.
For example, in my domain CGI/VFX, Python is used all around, but lua has growth in some places. For example it is used in Guerilla[0] and Katana[1], two software related to rendering and scene management. Technically a niche, but commercial product too. So, groups of people uses it all day but you will not find questions about it on stack overflow.
The reason to choose lua despite having Python all around is it's lightweight, apps can hack the VM for your specific needs, function call cost is faster and you can easily expand it with C (compared to Python).
This is just an example related to my domain, but I suspect this pattern is similar in many domains that doesn't pop on the internet. I suspect web dev is overexposed on the internet, making people thinking it's how dev runs all around.
I can recommend reading the performance page, it's a an engaging summary of the various tricks/optimisations that have been implemented https://luau-lang.org/performance
And here it is you learn it all. How to operate a OS and what to expect of it.
How to install a program.
And how to program.
Which means in 15 years, lua like syntax will push aside java-script, because this generation learned it in another way. Might aswell embrace it ahead of time.
Learned Future Preference dominance is gaming market dominance.
Would love to see these in the LuaJIT but I think its considered "done"
https://github.com/zewt/LuaJIT/commit/c0e38bacba15d0259c3b77...
> On some workloads it can match the performance of LuaJIT interpreter which is written in highly specialized assembly.
It's why you see it used as so many game's plugin architecture and why it was selected for NeoVim.
So there is a very large ecosystem of Lua code that just lives in Lua 5.1 and doesn't really push forward at all. I haven't checked in on the situation for some time, but most people who write Lua are writing Lua for something like NeoVim or WoW or some other plugin for a larger project. Those projects have no interest in dealing with the slow reference VM for Lua >=5.2 at this time.
Lua 5.2, 5.3, and 5.4 are more analogous to Python 2 to Python 3's level of change, rather than Python 3.9 to Python 3.10. These more recent versions of Lua 5.x are somewhat incompatible with each other, rather than just adding new language features.
Most products settle on Lua 5.1 because that is what luajit, a very fast just in time compiling implementation of the Lua VM supports. Plans to further support to new versions for luajit are...well they exist.
Does WoW use LuaJIT? I thought it used the reference Lua 5.1 VM, simply because that was the newest version when it was first released.
> Plans to further support to new versions for luajit are...well they exist.
I’m not sure it’ll ever happen. AFAICT LuaJIT is so complex that only its author, Mike Pall, understands it well enough to make major changes. He has expressed his dislike for several of the changes in Lua >= 5.2.
I didn’t mean to imply WoW was using luajit, apologies. I was under the impression that over the years they have patched and fussed with code of the reference VM to resolve some performance pain points in the vanilla UI lua. Unfortunately, I can’t find the source for that.
Regardless, I’ve always assumed that they had little interest in both rewriting their vanilla UI to newer versions AND starting over from square one trying to resolve any performance hiccups they hit.
Why is it so? Usually, when a language unlike Lua “evolves”, it just lacks a flipping lot of core/meta features from the beginning, crutch-adding them later. So users long for 1.x+ version so much, because 1.x is still bullshit, for any x. In case of Lua, its 5.1 version had some flaws, but it already had (arguably) more powerful execution/data model-wise than e.g. python or js, and these flaws were related to what the latter two haven’t had at all (because to them Lua is Lisp, in a sense of blub paradox). Coroutines, environments, metamethods, etc. 5.2 solved all of the remaining problems one way, LuaJIT another way. Upgrading to >5.2 doesn’t really change much in a way it works, but it’s enough to break your existing codebase.
So, “especially now” doesn’t have much weight in this case.
https://www.vocabulary.com/dictionary/luau, https://en.wikipedia.org/wiki/L%C5%AB%CA%BBau
Will subsequent derived languages be called luaua and luauau?
Assuming it's the same as "luau", which is a traditional Hawaiian feast, or –more frequently– a catch-all term for Hawaii-themed parties. [2]