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.
Have you considered using wasm as the foundation for Roblox, instead of Luau?
As it stands, we already have a high-performance, sandboxed VM that we are maintaining successfully, and our editor environment is decidedly _not_ multilingual for historical reasons/lack of investment. It'd be very, very expensive for us to see any of the advantages of wasm for the platform today, and it wouldn't really do anything about our existing need to support the millions of lines of code written in Luau today.
Also strategically, wasm is a massive project coordinated by a large number of companies, and it doesn't seem especially prudent to bet the success of a single multibillion dollar company and their entire platform on a project that they don't control the destiny of.
Agreed. I think an underappreciated aspect of choosing a script VM in the space Roblox is in (user-generated content where scripts are content) your product is at the mercy of whoever controls your scripting implementation.
The scripting engine is an integral part of your product, and you need to "own" it end-to-end. Any bugs that creep into new versions of your scripting engine, any API breakage or design changes that impact your usecase are things that you are responsible for. Roblox owns the entire toolchain for Luau, and it's relatively small compared to the set of libraries required to compile to and execute WASM in a performant way.
The nuances of your typical JITing WASM runtime or V8 are pretty hard to learn compared to a simpler VM like Luau, it's a big reason why I've used Luau in my own projects.
I use Luau with my Unity game for all gameplay code (60k+ loc so far). I agree the docs could be improved, especially for custom integrations. The new type system + LSP aren't great together yet either, and I've been a little worried about the direction since zeux left the team.
But otherwise I really like it. My Luau code hot reloads almost instantly while the game is running, and my C++ project compiles quickly when I update it. I like that it provides sandboxing if you want to support modding. And there's an active community of people on the official Discord, which is better than nothing.
Fast hot reload is not Luau specific though. Lua and LuaJIT reloads fast too, so does JS and most other scripting platforms. In fact, I have subsecond C++ hot-reloads.
Do you have a link for the official Luau Discord? I can't see anything on their webpage or github and google is not helpful either.
I mentioned fast hot reload because your original comment complained about compilation speed, and some people might not know you were referring to the speed of compiling your custom Luau integration in C++ (which is also fast for me, personally).
Sounds like the Discord I mentioned is technically the Roblox discord. The #luau-lang and #luau-lsp channels are where I lurk.
There's not an official Discord for Luau today (though it's something I've been considering setting up), but there is a Roblox open source community discord that the whole team is active in as part of our work on Luau.
Thanks for name-dropping zeux. Didn't know about him.
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?
Yes, I mean Luau itself, not the scripts.
In that case, wouldn't incremental builds solve this?
[dead]
What is the reason that LuaJIT was never updated past Lua 5.1?
Something that’s REALLY interesting is that Roblox is working on a Node.js style desktop runtime for Luau:
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.
Is the primary goal of the type system performance, or dev productivity, or something else?
If performance, are you comparing against a baseline that does the classic Self-style optimizations (like what JS engines do)?
FWIW I don't consider LuaJIT to be an interesting baseline because of what I've heard about it being overtuned to specific benchmark that the author(s) care about. (Too much of an attitude where if your code doesn't run well then it's your fault.)
I would say that the primary interest in building the type system is in supporting a better developer experience, both in terms of productivity (better autocomplete, go-to definition, etc.) and in terms of correctness (identifying bugs earlier, which is why we're actively concerned with having a _sound_ type system). There's a pretty limited surface of areas where we accept unsoundness today (outside of casting) and they're all connected to limitations of the type system that we've been working to resolve.
Longer-term, there's definitely some interest in how we could leverage types to support more optimized code, but it's been a notoriously difficult problem for gradually-typed languages in general, see [Is sound gradual typing dead?](https://dl.acm.org/doi/pdf/10.1145/2837614.2837630)
Gotcha. For some reason I was under the impression that getting perf from gradual typing had been a goal of y'all's.
> primary interest in building the type system is in supporting a better developer experience
Yeah this is the right reason to do it :-)
> there's definitely some interest in how we could leverage types to support more optimized code, but it's been a notoriously difficult problem for gradually-typed languages in general
I know. I still get folks asking why TypeScript types can't be used to make JS fast and it's quite exhausting to explain this.
Hard to imagine gradual types beating what you get from the combo of PICs, speculative JITing, and static analysis.
(I worked on JavaScriptCore's optimizer, hence why I'm curious about where y'all are coming from on this)
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 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!
Further, these extra components are easy to omit if you don't want to use them.
The REPL that we offer in the distribution doesn't include any of the analysis logic and it's just 1.7mb once compiled (on my M1 Macbook). I'm not sure how much smaller it gets if you omit CodeGen.
Luau can be pretty small if you need it to be.
I liked what I read, although the size of the original Lua embedded interpreter has a particular aesthetic that any type inference feature takes away (in return, you get type safety, it's a fair trade-off).
But when I tried it without reading to much, I got this (bug or feature)?
Code:
--!strict
local x: number = 2;
print("Hello World!")
x="test"
print(x)
Output:
Hello World!
test
There wasn't any error message or warning when I pressed the run button, and that certainly violated my expectations, regardless whether the code and behavior may be considered "correct" (=documented) or not.
The type system isn't set up to be "required" today. You can run code without typechecking, and if you used the demo or just ran the `luau` executable, that's what happened. In an embedded context, you could choose to e.g. require all code to typecheck before running the compiler on it, and then you'd get more of the experience you're probably expecting here, i.e. refusal to run because it didn't typecheck. This is part of how we exist in a world where we had millions of lines of Lua 5.1 code in the wild written by hundreds of thousands of developers that we suddenly, overnight, turned into Luau code.
I can recommend that people check out Lune [1], it's a Luau runtime which includes a small but nice standard library. It's very easy to create something like a webserver in it. [2]
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.
Luau isn't "Lua but with types," but rather a language in the Lua family that has grown a powerful gradual type system with a _ton_ of type inference (this is in contrast to e.g. TypeScript which takes the approach more of "add annotations to get benefits"), as well as a growing number of additions to the language that we believe make it a more pleasant developer experience to use. We're very focused on preserving the general ability to embed the language readily and with low costs to binary size and so forth, but we're less ruthlessly committed to the language's simplicity (for both better and worse). Overall, the goal is an embeddable language related to Lua with a focus on developer tooling and a positive developer experience such that people actually want to (and enjoy) build(ing) software in the language, rather than e.g. build large C projects and then expose them to Lua.
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.
At the very least, there's a common core of Lua 5.1 that works across Luau, LuaJIT, and PUC Lua, so it's not as if there's no standardization here. We definitely aspire to include _more_ than just Lua 5.1 in Luau though.
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.
This has been posted here a while ago but I'm pretty excited about bolt: https://github.com/Beariish/bolt - I've been looking for a statically typed language which could integrate well around something with a strong type system and good meta programming facilities for generating bindings. Bolt has the benefit of being a pretty small library with the downside of being nascent.
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.
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.
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.
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.
I actually came across https://github.com/PlutoLang/Pluto and it seems to be all the things you would want from Luau but without the connection to Roblox
Pluto seems cool, and I hadn't heard of it! Looks like they don't have a type system though, so it's more in the flavor of "extensions to Lua 5.4" than actively growing the language in a different direction than Lua itself has been growing.
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
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.
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.
Have you considered using wasm as the foundation for Roblox, instead of Luau?
As it stands, we already have a high-performance, sandboxed VM that we are maintaining successfully, and our editor environment is decidedly _not_ multilingual for historical reasons/lack of investment. It'd be very, very expensive for us to see any of the advantages of wasm for the platform today, and it wouldn't really do anything about our existing need to support the millions of lines of code written in Luau today.
Also strategically, wasm is a massive project coordinated by a large number of companies, and it doesn't seem especially prudent to bet the success of a single multibillion dollar company and their entire platform on a project that they don't control the destiny of.
Agreed. I think an underappreciated aspect of choosing a script VM in the space Roblox is in (user-generated content where scripts are content) your product is at the mercy of whoever controls your scripting implementation.
The scripting engine is an integral part of your product, and you need to "own" it end-to-end. Any bugs that creep into new versions of your scripting engine, any API breakage or design changes that impact your usecase are things that you are responsible for. Roblox owns the entire toolchain for Luau, and it's relatively small compared to the set of libraries required to compile to and execute WASM in a performant way.
The nuances of your typical JITing WASM runtime or V8 are pretty hard to learn compared to a simpler VM like Luau, it's a big reason why I've used Luau in my own projects.
I use Luau with my Unity game for all gameplay code (60k+ loc so far). I agree the docs could be improved, especially for custom integrations. The new type system + LSP aren't great together yet either, and I've been a little worried about the direction since zeux left the team.
But otherwise I really like it. My Luau code hot reloads almost instantly while the game is running, and my C++ project compiles quickly when I update it. I like that it provides sandboxing if you want to support modding. And there's an active community of people on the official Discord, which is better than nothing.
Fast hot reload is not Luau specific though. Lua and LuaJIT reloads fast too, so does JS and most other scripting platforms. In fact, I have subsecond C++ hot-reloads.
Do you have a link for the official Luau Discord? I can't see anything on their webpage or github and google is not helpful either.
I mentioned fast hot reload because your original comment complained about compilation speed, and some people might not know you were referring to the speed of compiling your custom Luau integration in C++ (which is also fast for me, personally).
Sounds like the Discord I mentioned is technically the Roblox discord. The #luau-lang and #luau-lsp channels are where I lurk.
There's not an official Discord for Luau today (though it's something I've been considering setting up), but there is a Roblox open source community discord that the whole team is active in as part of our work on Luau.
Thanks for name-dropping zeux. Didn't know about him.
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?
Yes, I mean Luau itself, not the scripts.
In that case, wouldn't incremental builds solve this?
[dead]
What is the reason that LuaJIT was never updated past Lua 5.1?
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 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
There's another standalone Luau runtime called Lune: https://github.com/lune-org/lune
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.
Is the primary goal of the type system performance, or dev productivity, or something else?
If performance, are you comparing against a baseline that does the classic Self-style optimizations (like what JS engines do)?
FWIW I don't consider LuaJIT to be an interesting baseline because of what I've heard about it being overtuned to specific benchmark that the author(s) care about. (Too much of an attitude where if your code doesn't run well then it's your fault.)
I would say that the primary interest in building the type system is in supporting a better developer experience, both in terms of productivity (better autocomplete, go-to definition, etc.) and in terms of correctness (identifying bugs earlier, which is why we're actively concerned with having a _sound_ type system). There's a pretty limited surface of areas where we accept unsoundness today (outside of casting) and they're all connected to limitations of the type system that we've been working to resolve.
Longer-term, there's definitely some interest in how we could leverage types to support more optimized code, but it's been a notoriously difficult problem for gradually-typed languages in general, see [Is sound gradual typing dead?](https://dl.acm.org/doi/pdf/10.1145/2837614.2837630)
Gotcha. For some reason I was under the impression that getting perf from gradual typing had been a goal of y'all's.
> primary interest in building the type system is in supporting a better developer experience
Yeah this is the right reason to do it :-)
> there's definitely some interest in how we could leverage types to support more optimized code, but it's been a notoriously difficult problem for gradually-typed languages in general
I know. I still get folks asking why TypeScript types can't be used to make JS fast and it's quite exhausting to explain this.
Hard to imagine gradual types beating what you get from the combo of PICs, speculative JITing, and static analysis.
(I worked on JavaScriptCore's optimizer, hence why I'm curious about where y'all are coming from on this)
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!
Further, these extra components are easy to omit if you don't want to use them.
The REPL that we offer in the distribution doesn't include any of the analysis logic and it's just 1.7mb once compiled (on my M1 Macbook). I'm not sure how much smaller it gets if you omit CodeGen.
Luau can be pretty small if you need it to be.
I liked what I read, although the size of the original Lua embedded interpreter has a particular aesthetic that any type inference feature takes away (in return, you get type safety, it's a fair trade-off).
But when I tried it without reading to much, I got this (bug or feature)?
Code:
Output: There wasn't any error message or warning when I pressed the run button, and that certainly violated my expectations, regardless whether the code and behavior may be considered "correct" (=documented) or not.The type system isn't set up to be "required" today. You can run code without typechecking, and if you used the demo or just ran the `luau` executable, that's what happened. In an embedded context, you could choose to e.g. require all code to typecheck before running the compiler on it, and then you'd get more of the experience you're probably expecting here, i.e. refusal to run because it didn't typecheck. This is part of how we exist in a world where we had millions of lines of Lua 5.1 code in the wild written by hundreds of thousands of developers that we suddenly, overnight, turned into Luau code.
I can recommend that people check out Lune [1], it's a Luau runtime which includes a small but nice standard library. It's very easy to create something like a webserver in it. [2]
[1]: https://lune-org.github.io/docs/
[2]: https://lune-org.github.io/docs/the-book/5-networking/#runni...
My entire personal website runs on a fork of Lune! Only change is a (very jank) crate I wrote to add SQLite.
>>> 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
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.
Luau isn't "Lua but with types," but rather a language in the Lua family that has grown a powerful gradual type system with a _ton_ of type inference (this is in contrast to e.g. TypeScript which takes the approach more of "add annotations to get benefits"), as well as a growing number of additions to the language that we believe make it a more pleasant developer experience to use. We're very focused on preserving the general ability to embed the language readily and with low costs to binary size and so forth, but we're less ruthlessly committed to the language's simplicity (for both better and worse). Overall, the goal is an embeddable language related to Lua with a focus on developer tooling and a positive developer experience such that people actually want to (and enjoy) build(ing) software in the language, rather than e.g. build large C projects and then expose them to Lua.
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.
At the very least, there's a common core of Lua 5.1 that works across Luau, LuaJIT, and PUC Lua, so it's not as if there's no standardization here. We definitely aspire to include _more_ than just Lua 5.1 in Luau though.
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.
This has been posted here a while ago but I'm pretty excited about bolt: https://github.com/Beariish/bolt - I've been looking for a statically typed language which could integrate well around something with a strong type system and good meta programming facilities for generating bindings. Bolt has the benefit of being a pretty small library with the downside of being nascent.
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.
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.
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.
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.
I actually came across https://github.com/PlutoLang/Pluto and it seems to be all the things you would want from Luau but without the connection to Roblox
Pluto seems cool, and I hadn't heard of it! Looks like they don't have a type system though, so it's more in the flavor of "extensions to Lua 5.4" than actively growing the language in a different direction than Lua itself has been growing.
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
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?