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.
[0] - https://github.com/lubgr/lua-cmake
[1] - https://github.com/amethyst/rlua/blob/master/examples/guided_tour.rsUsing 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.
If there actually is a correlation between high level languages and "trouble", it may be just because a high level language lets a less experienced developer (or team of developers) get farther than they otherwise would in some lower level language, i.e. the more cumbersome nature of a lower level language forces you to follow best practices earlier or the whole thing never gets off the ground, while the same sloppy devs + a higher level language might actually get as far as shipping something.
Whether that is ultimately better is debatable, but the problem is more how the tool is being used than something inherent in the tool itself.
https://github.com/yuin/gopher-lua Lua in Go
https://github.com/fengari-lua/fengari Lua in Javascript
Back in the late 80s before Python and Lua were released the following decades, TCL made sense, as it was the only freely available embedable language.
Python's larger and more complete (and I'd argue a better language then Lua), but Lua's compact and very fast as it's a register-based bytecode VM (and luaJIT exists which is even faster) (although if you don't use the 'local' keyword on variables, it's then quite a bit slower as it no longer uses stack-based variables, so the code can end up being more verbose to make it fast), so games commonly used Lua for scripting/gameplay as it was easy to integrate.
Back in 2004 or 2005, Firaxis decided to use Python as their embedded scripting language. They used something called “Boost Python”, a then reasonably easy to embed fork of Python, to embed Python2 in their Civilization 4 gaming engine.
Soon after this, Boost Python got abandoned and Firaxis ended up having to use an outdated version of Python by the time they released their final Civilization 4 expansion.
For Civilization 5, Firaxis instead used Lua, since they wanted an actively maintained code base.
For my own “embed a scripting language in a DNS server” project, I went with a slightly modified Lua 5.1. The entire DNS server, including the Lua scripting engine, is a 103,936 byte sized Windows service. The stack was a little hard to grok at first, but I was able to fairly quickly get used to it and have a Lua script set up configuration for the server, as well as parse DNS queries. [1]
To Python’s credit, the Python2 code used in Civilization 4 is 100% compatible with the final 2019 release of a Python2 interpreter, to the point that I can run map scripts for Civilization 4 -- compiled for x86/32-bit -- on a 64-bit ARM Raspberry Pi and have them generate the exact same maps. Useful when I wanted a particular kind of map for a Civ4 mod, and had to iterate through 300 different random seeds on my Raspberry Pi to find the desired kind of map. After about a month, I had over 180 map seeds meeting my criteria.
[1] https://github.com/samboy/MaraDNS/tree/master/deadwood-githu... for the record
[1] https://en.wikipedia.org/wiki/List_of_applications_using_Lua
To my knowledge, you can't do that with Python. I don't know about TCL though.
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...
I tried a bunch of different typed luas before landing on this project and having a really wonderful experience incrementally porting my most recent love2d thing over and then being able to make big architectural changes with confidence that types gave me.
I was able to do this port without modifying the original lua files, just replacing them with typescript one by one. Any lua libraries I was using I kept using by just writing some type declarations for then and throwing them in with the compiled output.
This is also a very good summary, and tracks with my own experience getting into Lua for Neovim scripting.
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
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.
-----
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.
return
f() return
f()
and return f()
You can also put multiple statements on the same line with no semicolons x=x+1 y=y+2We 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
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.
Sure, you can, but in practice you won't. For example, something like `local pos = {x, y}`. You now have to use 1/2 to access the x and y coords. Making the same table with 0 indexing is awkward and not idiomatic.
local ffi = require 'ffi'
local arr = ffi.new('float[?]', 100)
LuaJIT's FFI is pretty great. It puts even a lot of compiled languages to shame.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.
"lua 5.2 has no globals" is a bit of a misleading takeaway from the getfenf/setfenv changes in lua 5.2.
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.
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...
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.
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)