I used to use Lua and later LuaJIT in Lumix Engine. I switched to Luau because of its type system. However, it's apparent it was not meant to be used outside Roblox, as it has many rough corners. The documentation is not great, and the community is basically nonexistent - I got zero results when searching for any issues I encountered. Also, it's huge compared to Lua or LuaJIT, causing my project to compile 7x slower. The API is not great (e.g., an async API that blocks, using STL in the API, leaking STL headers). I encounter bugs with analysis/LSP often. Overall, I consider moving away from it.
We definitely intend on folks being able to use Luau outside of Roblox, and we know of a number of folks doing so quite successfully including Remedy Entertainment (Alan Wake 2), Digital Extremes (Warframe), GIANTS Software (Farming Simulator 25).
That being said, it has been historically hard to get major investment into work actively supporting growth of the language off-platform since our entire team is employed to work on the project by Roblox. We are nevertheless changing this though, and investing in the language outside of the platform. As some folks have already mentioned here, we have a general-purpose standalone runtime that we're developing called Lute that's focused on using Luau outside of Roblox to write general-purpose programs, and we're building a whole suite of Luau-programmable developer tools for the language atop it.
It takes time to build things, and the Luau ecosystem is definitely still very young as you've noted, but it's something that we care a lot about and are investing in considerably going forward. We 100% believe that the best thing for the health of the language and the ecosystem is to support more diverse users and more diverse use-cases.
Thanks for sharing your experience. I'm curious why it would cause your project to compile slower though? It's a scripting language, so you don't need to compile anything, right? Do you mean compiling the Luau VM itself?
Luau seems to be significantly more complex than Lua - I'm not sure it can still be called "small". Looking at the relative size of the implementations: Luau's is 120,000 lines of C++ [0], an order of magnitude larger than Lua 5.1's 14,000 lines of C.
But I think that complexity is unavoidable for a gradually- or statically-typed language. Any language with a reasonably-complete type system is inevitably going to be much more complex than a dynamically-typed scripting language.
[0] Counting *.cpp files in the "Analysis", "AST", "Compiler" and "VM" directories
Lua (and to a somewhat lesser extent Luau) are small in terms of the learned surface of the value language, not necessarily in terms of lines of code. That being said, any runtime use of the language needn't depend on Analysis, which is the biggest compilation unit by far.
Probably also worth mentioning that Analysis currently contains two full type system implementations because we've spent the better part of the past three years building a new type system to address a lot of the fundamental limitations and architectural issues that we'd run into after years of working on the original one. The new one is not without issues still, but is definitely very usable, and gets better and better every week. At some point in the future, we will clip the old one altogether, and that'll shave off some 30,000 lines of code or something.
I fully agree. Lua and Luau are impressive, sure, but they are not really "small" or "simple", in my view. I don't think the complexity is unavoidable however. There are many programming languages that are much simpler, but at the same time very expressive. I'm working on one of them currently named "Bau" [1], and I started working on a Lua-inspired VM [2] for a subset of this language. There are many languages like mine, most of them incomplete and not really popular, discussed in [3].
To be fair, both `Analysis` (the type-checker, not necessary at runtime or compile time) and `CodeGen` (the optional JIT engine) have no equivalent in PUC-Rio Lua.
If you look purely at the VM and things necessary to compile bytecode (AST, Compiler and VM) then the difference in code size isn't as stark.
Having worked with both Lua 5.1 and Luau VM code, Luau's codebase is a heck of a lot nicer to work on than the official Lua implementation even if it is more complex in performance-sensitive places. I have mixed feelings on the structural typing implementation, but the VM itself is quite good.
I learned about Luau via my 13 years old who is looking into Roblox Studio. That's how I ended up visiting luau.org and I'm quite impressed by Roblox's engineering on this.
Arseny Kapoulkine is an amazing engineer. Highly recommend following his blog or social media. Other than working on luau and the rendering engine at Roblox, he's also responsible for meshoptimizer which if you're in graphics you've most definitely heard of, and volk, which now comes packaged with the Vulkan SDK.
Teal compiles teal files into plain Lua just like TS does for JS. So all the advantages and disadvantages apply.
Luau is a backwards compatible superset of Lua that comes with it's own performance-tuned runtime. It offers more than just gradual typing.
So they are very different things. You can use Teal in cases when you don't control the runtime. Like write a Love2d game or your neovim config in it. Anywhere where Lua runs, you can use teal.
On the other hand Luau can offer superior developer experience because you don't have a separate compile step. They can do a lot more things that are impossible with teal as they have their own runtime and types do not get erased by compiling.
Teal transpiles to Lua, but Luau is a fork of Lua. Luau can implement wider ranging changes, like improving interpreter performance and security or adding syntactic sugar.
Roblox has a market cap near $100B and has multiple developers working full-time on Luau.
It's a shame that Lua did not evolve in a more backwards-compatible manner. In addition to Roblox, lots of others projects started adopting Lua 5.1 as a scripting language in the late 00s. Lua itself is now at 5.4, but it did not keep backwards compatibility. LuaJIT and related projects pretty much only support 5.1. It's similar to the situation Python had with 2.x/3.x, except that the majority of Lua users I am aware of are preferring to stay with the older 5.1.
It's hard to get reliable numbers on this but I believe 5.1 and 5.2 are both more popular than 5.4 which has been out for five years now. And I don't think 5.3 ever surpassed either of them. I'm not sure about luajit it gets a lot of attention but I don't see it around all that much.
I think it's even worse than that, luau and luaJIT have evolved in different directions than the official lua project, such that they are now all sublty incompatible with each others. They all branch from lua 5.1 but it feels like there isn't an offical standard anymore.
I know everyone hates bringing up naming conflicts, but I'm just going to say I think it's pretty lame to name a language so deeply inspired by another language, a name that is also insanely close to said language. Even the logo... I mean there's paying homage, then there's whatever this is.
Typed Lua is something I've always wanted, but writing a very comprehensive type-checker and LSP for another dynamic language is pretty difficult. All dynamic languages have similar problems to those TypeScript encountered, as most dynamic languages have a sort of structural typing in the form of dictionaries or objects.
I do wonder if we could reuse TypeScript in other dynamic languages.
Transform Luau to a subset of TypeScript, check with tsc, transform errors and results back to Luau. In the same way, one could reuse a TypeScript language server. This way of utilising TypeScript's engine could jump-start many other type checkers for other dynamic languages.
Luau already has Luau Language Server which works extremely well for vscode w/ nvim & zed support as well. It surfaces Luau's own diagnostics w/ autocomplete, strict type checking, etc., leading to a better DX (for me) than using Ruby or Python. I primarily use Luau as a shell scripting & general purpose programming language w/ my own runtime (ala node is to js) called seal. Many Roblox devs use a different (much more popular) runtime called Lune for Roblox CI/CD, unit & integration testing, etc.
Like a LLVM but for type systems instead of compilation / interpreters / JIT. I don’t see why that couldn’t work.
My thinking in this space has always started from a type inferred MetaLanguage but starting from a dynamic language does enable some interesting options. I tend not to touch dynamic languages, even going so far as to use transpilers, but I definitely would be more open to the idea of working with them if they had TypeScript level of gradual type checking and tool support. As you mention such a bidirectional transpiler would work I guess for things that don’t translate it could just give up and that’ll be part of the gradual typing aspect.
I would love to have TypeScripts type system on a Lua runtime, so I’ve been keeping an eye on Luau.
What I meant was transpiling Luau (in memory or cached to disk) -> TypeScript -> typecheck with tsc -> take error outputs and line numbers -> transform back to Luau code via sourcemaps etc. This is potentially way easier than making your own checker for another structurally typed language.
User only sees Luau script in their editor, but it gets checked by TSC in the background.
Roblox might is such a big maker that they can re-invent the whole structural typing themselves, so they don't need to do that.
For all its success typescript demonstrates the downside of this approach. Like you said it's just difficult, and the end result of having every corner of the dynamic language expressible in the type system forces you into the most complex & novel type systems.
IMO a better approach is the one used by rescript and gleam. With a few careful restrictions of the target language you can fit it into a hindley-milner type system. These are extremely well understood, robust & usable, and give you a much smaller interface than the expansive turing complete one of TS.
I'm kind of surprised there's not an active project for a small ML language outputting lua code. I really wish gleam could pick it up as a third backend, it would be an amazing fit.
I used to use Lua and later LuaJIT in Lumix Engine. I switched to Luau because of its type system. However, it's apparent it was not meant to be used outside Roblox, as it has many rough corners. The documentation is not great, and the community is basically nonexistent - I got zero results when searching for any issues I encountered. Also, it's huge compared to Lua or LuaJIT, causing my project to compile 7x slower. The API is not great (e.g., an async API that blocks, using STL in the API, leaking STL headers). I encounter bugs with analysis/LSP often. Overall, I consider moving away from it.
We definitely intend on folks being able to use Luau outside of Roblox, and we know of a number of folks doing so quite successfully including Remedy Entertainment (Alan Wake 2), Digital Extremes (Warframe), GIANTS Software (Farming Simulator 25).
That being said, it has been historically hard to get major investment into work actively supporting growth of the language off-platform since our entire team is employed to work on the project by Roblox. We are nevertheless changing this though, and investing in the language outside of the platform. As some folks have already mentioned here, we have a general-purpose standalone runtime that we're developing called Lute that's focused on using Luau outside of Roblox to write general-purpose programs, and we're building a whole suite of Luau-programmable developer tools for the language atop it.
It takes time to build things, and the Luau ecosystem is definitely still very young as you've noted, but it's something that we care a lot about and are investing in considerably going forward. We 100% believe that the best thing for the health of the language and the ecosystem is to support more diverse users and more diverse use-cases.
Thanks for sharing your experience. I'm curious why it would cause your project to compile slower though? It's a scripting language, so you don't need to compile anything, right? Do you mean compiling the Luau VM itself?
Something that’s REALLY interesting is that Roblox is working on a Node.js style desktop runtime for Luau:
https://github.com/luau-lang/lute
There's another standalone Luau runtime called Lune: https://github.com/lune-org/lune
there's a slightly more mature runtime for Luau developed already:
https://github.com/lune-org/lune
i use it for build scripts and automating tasks for Roblox place files, it's pretty good for my use-case
Luau seems to be significantly more complex than Lua - I'm not sure it can still be called "small". Looking at the relative size of the implementations: Luau's is 120,000 lines of C++ [0], an order of magnitude larger than Lua 5.1's 14,000 lines of C.
But I think that complexity is unavoidable for a gradually- or statically-typed language. Any language with a reasonably-complete type system is inevitably going to be much more complex than a dynamically-typed scripting language.
[0] Counting *.cpp files in the "Analysis", "AST", "Compiler" and "VM" directories
Lua (and to a somewhat lesser extent Luau) are small in terms of the learned surface of the value language, not necessarily in terms of lines of code. That being said, any runtime use of the language needn't depend on Analysis, which is the biggest compilation unit by far.
Probably also worth mentioning that Analysis currently contains two full type system implementations because we've spent the better part of the past three years building a new type system to address a lot of the fundamental limitations and architectural issues that we'd run into after years of working on the original one. The new one is not without issues still, but is definitely very usable, and gets better and better every week. At some point in the future, we will clip the old one altogether, and that'll shave off some 30,000 lines of code or something.
I fully agree. Lua and Luau are impressive, sure, but they are not really "small" or "simple", in my view. I don't think the complexity is unavoidable however. There are many programming languages that are much simpler, but at the same time very expressive. I'm working on one of them currently named "Bau" [1], and I started working on a Lua-inspired VM [2] for a subset of this language. There are many languages like mine, most of them incomplete and not really popular, discussed in [3].
[1] https://github.com/thomasmueller/bau-lang [2] https://github.com/thomasmueller/bau-lang/blob/main/src/test... [3] https://www.reddit.com/r/ProgrammingLanguages/
To further elaborate, here's a more detailed breakdown of tokei's line counts for each of the directories you list + the CodeGen directory:
- Analysis: 62821 lines of C++ code, 9254 lines of C headers
- Ast: 8444 lines of C++, 2582 lines of C headers
- CodeGen: 21678 lines of C++, 4456 lines of C headers
- Compiler: 7890 lines of C++, 542 lines of C headers
- VM: 16318 lines of code, 1384 lines of C headers
Compare to Lua 5.1, which tokei says has 11104 lines of C and 1951 lines of C headers in the src/ directory.
To be fair, both `Analysis` (the type-checker, not necessary at runtime or compile time) and `CodeGen` (the optional JIT engine) have no equivalent in PUC-Rio Lua.
If you look purely at the VM and things necessary to compile bytecode (AST, Compiler and VM) then the difference in code size isn't as stark.
Having worked with both Lua 5.1 and Luau VM code, Luau's codebase is a heck of a lot nicer to work on than the official Lua implementation even if it is more complex in performance-sensitive places. I have mixed feelings on the structural typing implementation, but the VM itself is quite good.
> If you look purely at the VM and things necessary to compile bytecode (AST, Compiler and VM) then the difference in code size isn't as stark.
I suspected as much, but I didn't want to guess since I'm not familiar with either codebase. Thanks for the info!
>>> Luau interpreter can be competitive with LuaJIT interpreter depending on the program
To me, this is the more interesting bit of luau
The performance page[1] contains a pretty good explanation of the work they have done. Pretty impressive engineering if you ask me.
[1] https://luau.org/performance
I learned about Luau via my 13 years old who is looking into Roblox Studio. That's how I ended up visiting luau.org and I'm quite impressed by Roblox's engineering on this.
Arseny Kapoulkine is an amazing engineer. Highly recommend following his blog or social media. Other than working on luau and the rendering engine at Roblox, he's also responsible for meshoptimizer which if you're in graphics you've most definitely heard of, and volk, which now comes packaged with the Vulkan SDK.
How does Luau compare to Teal [0], which is described similarly as a "statically-typed dialect of Lua"?
[0] https://teal-language.org/
Teal compiles teal files into plain Lua just like TS does for JS. So all the advantages and disadvantages apply.
Luau is a backwards compatible superset of Lua that comes with it's own performance-tuned runtime. It offers more than just gradual typing.
So they are very different things. You can use Teal in cases when you don't control the runtime. Like write a Love2d game or your neovim config in it. Anywhere where Lua runs, you can use teal.
On the other hand Luau can offer superior developer experience because you don't have a separate compile step. They can do a lot more things that are impossible with teal as they have their own runtime and types do not get erased by compiling.
Teal transpiles to Lua, but Luau is a fork of Lua. Luau can implement wider ranging changes, like improving interpreter performance and security or adding syntactic sugar.
Roblox has a market cap near $100B and has multiple developers working full-time on Luau.
It's a shame that Lua did not evolve in a more backwards-compatible manner. In addition to Roblox, lots of others projects started adopting Lua 5.1 as a scripting language in the late 00s. Lua itself is now at 5.4, but it did not keep backwards compatibility. LuaJIT and related projects pretty much only support 5.1. It's similar to the situation Python had with 2.x/3.x, except that the majority of Lua users I am aware of are preferring to stay with the older 5.1.
It's hard to get reliable numbers on this but I believe 5.1 and 5.2 are both more popular than 5.4 which has been out for five years now. And I don't think 5.3 ever surpassed either of them. I'm not sure about luajit it gets a lot of attention but I don't see it around all that much.
I think it's even worse than that, luau and luaJIT have evolved in different directions than the official lua project, such that they are now all sublty incompatible with each others. They all branch from lua 5.1 but it feels like there isn't an offical standard anymore.
I know everyone hates bringing up naming conflicts, but I'm just going to say I think it's pretty lame to name a language so deeply inspired by another language, a name that is also insanely close to said language. Even the logo... I mean there's paying homage, then there's whatever this is.
Luau was named Luau before Luau was a different language
Typed Lua is something I've always wanted, but writing a very comprehensive type-checker and LSP for another dynamic language is pretty difficult. All dynamic languages have similar problems to those TypeScript encountered, as most dynamic languages have a sort of structural typing in the form of dictionaries or objects.
I do wonder if we could reuse TypeScript in other dynamic languages.
Transform Luau to a subset of TypeScript, check with tsc, transform errors and results back to Luau. In the same way, one could reuse a TypeScript language server. This way of utilising TypeScript's engine could jump-start many other type checkers for other dynamic languages.
Luau already has Luau Language Server which works extremely well for vscode w/ nvim & zed support as well. It surfaces Luau's own diagnostics w/ autocomplete, strict type checking, etc., leading to a better DX (for me) than using Ruby or Python. I primarily use Luau as a shell scripting & general purpose programming language w/ my own runtime (ala node is to js) called seal. Many Roblox devs use a different (much more popular) runtime called Lune for Roblox CI/CD, unit & integration testing, etc.
Like a LLVM but for type systems instead of compilation / interpreters / JIT. I don’t see why that couldn’t work.
My thinking in this space has always started from a type inferred MetaLanguage but starting from a dynamic language does enable some interesting options. I tend not to touch dynamic languages, even going so far as to use transpilers, but I definitely would be more open to the idea of working with them if they had TypeScript level of gradual type checking and tool support. As you mention such a bidirectional transpiler would work I guess for things that don’t translate it could just give up and that’ll be part of the gradual typing aspect.
I would love to have TypeScripts type system on a Lua runtime, so I’ve been keeping an eye on Luau.
It already exists actually: https://github.com/TypeScriptToLua/TypeScriptToLua.
I had a pretty good experience with it while trying out Love2D.
That is one way.
What I meant was transpiling Luau (in memory or cached to disk) -> TypeScript -> typecheck with tsc -> take error outputs and line numbers -> transform back to Luau code via sourcemaps etc. This is potentially way easier than making your own checker for another structurally typed language.
User only sees Luau script in their editor, but it gets checked by TSC in the background.
Roblox might is such a big maker that they can re-invent the whole structural typing themselves, so they don't need to do that.
For all its success typescript demonstrates the downside of this approach. Like you said it's just difficult, and the end result of having every corner of the dynamic language expressible in the type system forces you into the most complex & novel type systems.
IMO a better approach is the one used by rescript and gleam. With a few careful restrictions of the target language you can fit it into a hindley-milner type system. These are extremely well understood, robust & usable, and give you a much smaller interface than the expansive turing complete one of TS.
I'm kind of surprised there's not an active project for a small ML language outputting lua code. I really wish gleam could pick it up as a third backend, it would be an amazing fit.
It is an impressive achievement.
Unfortunately, there is not a Luau distribution of windows like Luarocks.
Eventually we may see something in this place.
The well known libraries, IUP, CD, IM have not been ported to Luau.
But code is Free Open Source, who knows.
Coward, make it statically-typed!
Does it fix array indexing starting from 1?