Lua is a very nice piece of technology. Its source code is pretty easy to get into, the documentation is complete.
It has its quirks yes, but if I need to add scripting to a software, I'd consider Lua before considering writing a DSL, simply because you can pretty much embed Lua's source in your C/C++ software as a static library[0].
The stack-based approach makes it so easy to interact with C/C++, and I've been looking at the Rust bindings[1] recently out of curiosity, looks promising.
If you need a few line here an there scripting, sure Lua, JS, PHP... whatever works.
Using these languages for large projects is where the trouble starts: as they push you towards bad solutions that we know are bad for many decades. You need clear description of how to avoid these pittfals, or your growing codebase slowly becomes unmanageable.
I ended up ditching a growing Lua codebase for this reason. Get out before it gets to big to get out.
At first Lua seems strange, but after a while you start to appreciate it. It’s designed with a small number of concepts that manage to lead to expressive code with excellent performance.
I use it for two things: scripting TeX¹, where it allows you to do amazing things², even complex numerical calculations³ within the document; and writing Pandoc filters, where it is now the standard method.
I really appreciate that the article has a "Different" section for things that are different from, but not necessarily better or worse than, other programming languages.
This is also a very good summary, and tracks with my own experience getting into Lua for Neovim scripting.
This was written just after Lua 5.2 was released. There have been improvements since then. Lua 5.3 introduced an integer type (64-bit), actual Boolean operators, a UTF-8 library, a way to yield across a C-boundary and a way to pack and unpack binary data. Lua 5.4 introduced deterministic finalizers (and a fall out from that is a limited form of constant local variables).
Lua appeals to my sensibilites and I want to make use of it. It seems to be a well-designed language and it has a very performant JIT. But a big weakness for non-embedded use cases seems to be its ecosystem. A recent little project I wanted to use Lua on included a sqlite database, oldschool 3DES encryption, and an SMTP client. For many languages, there would be a clearly mob-approved library for each of these. But I found 3 or 4 possibilities to use sqlite in Lua, with no clear winner. I ended up using Ruby instead.
While what you went through and felt is valid, I was able to find, in LuaRocks, libraries or Lua interfaces to libraries implementing everything on that wish list. In more detail:
In my limited experience, when you want to interact with C libraries, you often end up reading the docs of the original C library anyway because often the bindings are nearly 1:1 - and often the trouble lies in the word "nearly".
Just writing yourself the bindings you actually need is most likely the best approach.
It should be relatively easy to do, because by using something like Lua you goal is precisely to expose functionalities implemented by your language as Lua functions (otherwise you would just convert them into dynamic library functions and use a classic glue language with a decent FFI to connect them).
This is the value proposition of an embeddable scripting language at heart.
I work on a project that leverages Kong's API Gateway, which is essentially Nginx + Openresty (Lua) + Kong (More Lua). The killer feature wrt Kong is the plugin ecosystem, which (among other things) allows you to act on the request/response lifecycle at various stages. Developers coming onboard to the project usually have little to no experience writing Lua, but we've found that coming up to speed on the language and it's runtime to be fairly painless. These days Kong has shims to write plug-in code in a few different languages (javascript, python, go, and more recently a wasm runtime) but despite our teams unfamiliarity with the language we still go back to Lua because performance can't be beat.
I’ve had a very positive experience using Lua as an extension language.
I was writing a text editor at the time. I wanted as much of the core code/actions to be written in Lua as possible, as I’ve always disliked very thin scripting APIs that sit on top of opaque native procedures.
I was able to wrap a handful of native functions in Lua code, then write the remaining 85% of the editor core in Lua. Everything was very fast and the process was straightforward. I’d definitely choose it again.
Lua 5.4 now includes a short utf8 library in the standard library. It has ways ways to get the utf8 string length and regex patterns for utf8 codepoints. However, it doesn't include any functionality that would require large tables of characters (for example, knowing which unicode characters are alphabetical).
-----
The requirement that return be the last statement is to avoid a syntactic ambiguity. Since Lua has no semicolons, there would be no way to know whether a line following the return statement is part of the return statement.
You can also write rust ( or go, or write in any other language that allows you to expose a C ABI ) and make a Lua module. This solves a number of the different, bad and ugly issues in my opinion. For example, I think using rust’s chrono or unicode_segmentation library makes life so much easier than having to deal with that in Lua. Neovim embeds lua 5.1 jit, and it’s possible to write plugins in rust for neovim using this mechanism.
For any one that knows what I’m talking about it should be obvious how to do this. If not, I wrote about this more here, in case you are interested:
The timestamps next to the two oldest replies make it seem like they were more recently submitted, too. But I think they are 4 days old.
Seems like the title should be "Lua: Good, Different, Bad and Ugly Parts" as there is a fourth section, preceding "Bad", in the blog post called "Different".
Language wonks can endlessly dismiss Lua as a programming language, but it continues to be "embdedded in", i.e., used to extend, useful network applications, e.g., dnsdist, haproxy, nmap. To learn to use the application to its fullest, one has to learn some Lua.
A missing 'good' - the reference implementation is extremely easy to extend with existing C or lua libraries. E.g. embed sqlite.c and bindings to it and all of penlight (a bunch of standard library like utilities written in lua).
There are some package managers. However concatenating all the source plus a bunch of libraries into one .c file also works great, My bootstrap/install is to clone that one file via git and feed it to clang.
For better or worse, the language devs have a goal of keeping things simple, so this would have to be provided by a library. It's pretty easy to implement this sort of thing in luajit or provide that library to other luas though.
"Please don't complain about tangential annoyances—things like article or website formats, name collisions, or back-button breakage. They're too common to be interesting."
[+] [-] linkdd|4 years ago|reply
It has its quirks yes, but if I need to add scripting to a software, I'd consider Lua before considering writing a DSL, simply because you can pretty much embed Lua's source in your C/C++ software as a static library[0].
The stack-based approach makes it so easy to interact with C/C++, and I've been looking at the Rust bindings[1] recently out of curiosity, looks promising.
[+] [-] aeternum|4 years ago|reply
[+] [-] cies|4 years ago|reply
Using these languages for large projects is where the trouble starts: as they push you towards bad solutions that we know are bad for many decades. You need clear description of how to avoid these pittfals, or your growing codebase slowly becomes unmanageable.
I ended up ditching a growing Lua codebase for this reason. Get out before it gets to big to get out.
[+] [-] VWWHFSfQ|4 years ago|reply
[0] https://github.com/khvzak/mlua
[+] [-] xvilka|4 years ago|reply
[1] https://github.com/kyren/luster
[+] [-] lmm|4 years ago|reply
[+] [-] leephillips|4 years ago|reply
I use it for two things: scripting TeX¹, where it allows you to do amazing things², even complex numerical calculations³ within the document; and writing Pandoc filters, where it is now the standard method.
1 ‘LuaTeX comes of age’. LWN. Available from: https://lwn.net/Articles/731581/
2 http://wiki.luatex.org/index.php/TeX_without_TeX
3 http://www.unirioja.es/cu/jvarona/downloads/numerical-method...
[+] [-] nerdponx|4 years ago|reply
This is also a very good summary, and tracks with my own experience getting into Lua for Neovim scripting.
[+] [-] spc476|4 years ago|reply
[+] [-] BoogerDan|4 years ago|reply
[+] [-] strenholme|4 years ago|reply
a sqlite database
https://luarocks.org/modules/tami5/sqlite
https://luarocks.org/modules/dougcurrie/lsqlite3
3DES encryption
https://luarocks.org/modules/starius/luacrypto
https://github.com/somesocks/lua-lockbox/blob/master/lockbox...
an SMTP client
https://luarocks.org/modules/luarocks/lua-smtps
[+] [-] astrobe_|4 years ago|reply
Just writing yourself the bindings you actually need is most likely the best approach.
It should be relatively easy to do, because by using something like Lua you goal is precisely to expose functionalities implemented by your language as Lua functions (otherwise you would just convert them into dynamic library functions and use a classic glue language with a decent FFI to connect them).
This is the value proposition of an embeddable scripting language at heart.
[+] [-] monatron|4 years ago|reply
[+] [-] jonpalmisc|4 years ago|reply
I was writing a text editor at the time. I wanted as much of the core code/actions to be written in Lua as possible, as I’ve always disliked very thin scripting APIs that sit on top of opaque native procedures.
I was able to wrap a handful of native functions in Lua code, then write the remaining 85% of the editor core in Lua. Everything was very fast and the process was straightforward. I’d definitely choose it again.
[+] [-] ufo|4 years ago|reply
-----
The requirement that return be the last statement is to avoid a syntactic ambiguity. Since Lua has no semicolons, there would be no way to know whether a line following the return statement is part of the return statement.
[+] [-] delusional|4 years ago|reply
[+] [-] kdheepak|4 years ago|reply
For any one that knows what I’m talking about it should be obvious how to do this. If not, I wrote about this more here, in case you are interested:
https://blog.kdheepak.com/loading-a-rust-library-as-a-lua-mo...
[+] [-] 1vuio0pswjnm7|4 years ago|reply
https://news.ycombinator.com/user?id=Svetlitski
The timestamps next to the two oldest replies make it seem like they were more recently submitted, too. But I think they are 4 days old.
Seems like the title should be "Lua: Good, Different, Bad and Ugly Parts" as there is a fourth section, preceding "Bad", in the blog post called "Different".
Language wonks can endlessly dismiss Lua as a programming language, but it continues to be "embdedded in", i.e., used to extend, useful network applications, e.g., dnsdist, haproxy, nmap. To learn to use the application to its fullest, one has to learn some Lua.
[+] [-] josephcsible|4 years ago|reply
[+] [-] unknown|4 years ago|reply
[deleted]
[+] [-] JonChesterfield|4 years ago|reply
There are some package managers. However concatenating all the source plus a bunch of libraries into one .c file also works great, My bootstrap/install is to clone that one file via git and feed it to clang.
[+] [-] dang|4 years ago|reply
Lua: Good, bad, and ugly parts - https://news.ycombinator.com/item?id=6616817 - Oct 2013 (19 comments)
Lua: Good, bad, and ugly parts - https://news.ycombinator.com/item?id=5348513 - March 2013 (110 comments)
[+] [-] erwincoumans|4 years ago|reply
We used to ship lua binaries for the premake build system.
For me, the indexed from 1 rather than 0 is a big turn off.
Roblox has the mlua fork, with increased performance and added type annotations: https://github.com/Roblox/luau
[+] [-] diego_moita|4 years ago|reply
I can't understand why people complain about that.
If you're using 'pairs(table)' iteration then the index doesn't matter.
If you're accessing indexes directly you can have the index '0' in a table.
[+] [-] chirsz|4 years ago|reply
[+] [-] edflsafoiewq|4 years ago|reply
[+] [-] anonymoushn|4 years ago|reply
[+] [-] anonymoushn|4 years ago|reply
"lua 5.2 has no globals" is a bit of a misleading takeaway from the getfenf/setfenv changes in lua 5.2.
[+] [-] dang|4 years ago|reply
[+] [-] jbotz|4 years ago|reply
[+] [-] daneel_w|4 years ago|reply
[+] [-] Normille|4 years ago|reply
[deleted]
[+] [-] dang|4 years ago|reply
https://news.ycombinator.com/newsguidelines.html