Lua 5.5 Released
109 points by theelx
109 points by theelx
I'm not really into Lua, but I want to ask, what is the state of LuaJIT right now? Last time I checked it was a few versions behind Lua main implementation
It's a weird mixture of Lua 5.1, 5.2 and 5.3 without being compatible with 5.2 or 5.3. Mike Pall, author of LuaJIT, had a major disagreement with how 5.2+ deals with global values and modules, and refused to adapt. He did, however, add some modules from 5.2 and 64-bit integer support (5.3---I think, I haven't followed LuaJIT all that much).
Lua versions have backwards incompatible changes, including 5.5 as just released, so Luajit can’t support all of a new version without breaking existing code. Luajit adopts select features from later versions which basically makes it an n+1th dialect of Lua, where n = 5 now.
There are some incompatibilities that are unlikely to ever be resolved. However, unless you're doing a lot of numerics, it's usually fairly easy to write library code that targets LuaJIT along with the mainline versions.
Writing application code that's compatible across both is a little more difficult, but you almost never have to--when you're writing an application you usually already know what version of Lua you need to run under.
Looks like great changes, mostly. (I'm a little baffled by the inclusion of table.create but whatever.) The biggest surprise is that they finally added global. Not that it's a bad change; on the contrary it's a great change, but I assumed that since they refused to add it in earlier versions despite its great utility and ease of implementation, that they had been intentionally refusing on some other grounds. I wonder why it wasn't added earlier.
I believe the point of table.create is that you can pass in a number, a number of values for which Lua will preallocate memory in the table.
Since posting this I have come across a few people who say that they have needed this preallocation functionality before, but up until this day I had never heard of anyone needing it.
It's just strange because they refuse to include things like a function for ls, which is something like 80% of Lua programmers would benefit from, but then they go and include this very obscure function. Not that I'm a language maximalist, but it's hard to understand what the rationale is for what makes the cut and what doesn't.
table.create() is a Lua wrapper around the lua_createtable() function which has been part of Lua’s C API since 5.1 or before. LuaJIT has a similar wrapper called table.new().
Lua can’t list directories because ISO C can’t list directories.
I would have at least expected a mention in https://www.lua.org/manual/5.5/manual.html#3.4.9 as well but maybe they will amend it.
Lua can’t list directories because ISO C can’t list directories.
This hasn't stopped them from adding readline support.
Readline is an optional repl user interface feature, not part of the language’s standard library.
A more interesting nonportable feature is dlopen() for libraries; I guess the argument is that package.searchers is an extension point and dynamic loading is an extension included in the default configuration? Maybe.
I guess the argument is that...
This rang a bell for me, and I found the following in Ierusalimschy's Programming in Lua (2nd edition, 8.2):
Unlike code written in Lua, C code needs to be linked with an application before use. In most popular systems, the easiest way to do this link is with a dynamic linking facility. However, this facility is not part of the ANSI C specification; that is, there is no portable way to implement it.
Normally, Lua does not include any facility that cannot be implemented in ANSI C. However, dynamic linking is different. We can view it as the mother of all other facilities: once we have it, we can dynamically load any other facility that is not in Lua. Therefore, in this particular case, Lua breaks its portability rules and implements a dynamic linking facility for several platforms. The standard implementation offers this support for Windows, Mac OS X, Linux, FreeBSD, Solaris, and some other Unix implementations. It should not be difficult to extend this facility to other platforms; check your distribution.
It's just strange because they refuse to include things like a function for ls, which is something like 80% of Lua programmers would benefit from
I’m not certain that this is true. Lua’s great strength is that it is easy to embed in other programs. Most of the places where I have used it, it has been embedded in an environment where it does not have filesystem access.
Lua’s great strength is that it is easy to embed in other programs.
This is selling it short; Lua's greatest strength is that it's a well-designed language that leans heavily on lexical scope and includes almost no bad features that are common in other "scripting" languages. It's tremendously useful outside embedded contexts too.
It's tremendously useful outside embedded contexts too.
I agree but only if you are willing to do a lot that most other languages provide for you. I enjoy programming in Lua more than any other language I've worked with, but I gave it up (first for Python and now for Go) because the standard library is so minimal. Like a lot of people who write Lua, I wrote all sorts of things to support non-embedded Lua programs: a string split function and iterator, a utility package for tables (to provide map, grep, clone, a test for deep equality, etc.), several option parsers, a couple of assertion libraries, and several testing libraries. Eventually I got tired of the yak shaving and I also worried that I didn't know enough to write such basic libraries well enough.
The language's creators are determined to keep the language minimal and embeddable. They have made a very deliberate choice to keep Lua a no-batteries-included language. As long as that is the case, I think that it's reasonable for people to think of Lua as primarily a embedded language.
Eventually I got tired of the yak shaving and I also worried that I didn't know enough to write such basic libraries well enough.
I don't understand what this means; why did you write the same functions over and over instead of bringing in an existing library for it? The fact that I can choose for myself what I want to bring in instead of dragging around decades of crufty stdlib crap that contain three ways to do the same thing is one of my favorite things about Lua.
Sorry that I wasn't more clear. I didn't write the same functions over and over. I wrote different libraries for the same domains either after I learned the domain better or after my needs or taste changed. I know that many people say that standard libraries are filled with crufty crap, but that hasn't been my experience with, e.g., Python and Go. On the other hand, I find it difficult and time-consuming to vet and to choose between third-party libraries. Maybe my experiences are unusual or my needs are idiosyncratic, but that's why I wish that Lua had a larger standard library.
Anyhow, all of this is irrelevant. Here's my main point: it was perfectly reasonable for David to say that "Lua’s great strength is that it is easy to embed in other programs." That doesn't mean—or imply—that Lua is only good for embedding. But it's certainly known for that—and for good reason. As the official "About Lua" page says, "Lua has been used in many industrial applications...with an emphasis on embedded systems...and games."
I have added a similar function to several Lua + C code bases, it has long been a well-known way to optimize some programs.
Similarly external strings are a very welcome addition.
I love Lua. There's something to be said for a language so small that no one's stressed about mastering it.
I like the idea of Lua, but there’s only so many times I can write
local new_list = {}
for _, item in ipairs(old_list)
table.insert(new_list, f(item))
end
return new_list
before getting frustrated. I think Janet is what Lua should have been.
It's very rare that I find myself writing Lua code without any 3rd-party libraries. Lume is fairly small and very stable but gives you:
local new_list = lume.map(old_list, f)
I'm similarly surprised of seeing Lua constantly lauded in online discussions.
Granted I only used it for Redis and Nginx scripting, but the table type as well as the "all numbers are float" gives me some weird JS/PHP vibes. I get that it's small end efficient for what it tries to be, but I never managed to enjoy it.
the table type as well as the "all numbers are float" gives me some weird JS/PHP vibes.
It does indeed have PHP/JS vibes, in the sense that it is brutally pragmatic while disregarding theoretical correctness elegance. It's get-stuff-done-first.
People rave about it, because it provides high level programming possibilities in many places via embedding, eliminating the need to bring in more pieces to a system. The fact the the syntax is short, ensures that it can be learned fast.
Think: it can be done, rather than: what tech diner need to add.
Case point, nginx scripting. Almost all web services i worked with, could be written in Lua using openresty. Personally, I rarely see any real advantage of using other language and out it behind nginx. There is a sense of satisfaction in reducing a system to it's canonical form.
it is brutally pragmatic while disregarding theoretical correctness elegance. It's get-stuff-done-first.
Well, that's where I think @xigoi example is perfect. I don't see anything pragmatic nor "get-stuff-done" in having such a contrived way to iterate over a list.
But I suppose most of the audience is people integrating Lua in larger apps implemented in a lower-level language like C/C++, so I get that in comparison it seems that way.
It's just that from my point of view (someone working mostly with Ruby), numerous other "scripting language" have a much better ergonomic, including Javascript. But I get that Lua has somewhat cornered the embedded scripting market.
https://janet-lang.org/docs/syntax.html#Grammar means it is unlikely to reach the same target audience as Lua. Plus, https://janet-lang.org/docs/syntax.html#:~:text=there%20are%20no%20multiline%20comments isn't doing itself any favors for winning over the Lua crowd
What specifically about the grammar do you consider a problem? Lua’s grammar does not seem to be formally specified anywhere, but it would probably be similarty, if not more, complex.
As for multiline comments, I’ve never missed them. Any usable text editor has a shortcut to comment out multiple lines.
I didn't mean complexity, I meant the family - if one is trying to glue a scripting language on to their C/C++/C#/game then it is very unlikely they're going to go from void extension_method() { janet_init(&state); } to (defun (ok-different-thought-process ,(@[with what now]))) to say nothing of trying to reach other audiences (e.g. folks who are not the original author who wish to contribute)
Lua is also very different from C. I don’t see why this argument wouldn’t apply to it too.
C and Lua both come from the ALGOL family of syntax, whose shape is largely familiar to most programmers. Janet's syntax is much more Lisp shaped, and that scares some people off.
Is it unfair or incorrect for people to care about syntax like that? Maybe. But it's human nature, it does matter for adoption, and that's what I think @mdaniel was getting at re: reaching audiences.
(I write this as someone who likes Janet and wishes he had an excuse to use it more.)
https://www.lua.org/manual/5.5/manual.html#9 is cited as extended BNF but like many specifications only trying to use it in anger against code in the wild could say for sure whether it's accurate or not, and I didn't bother downloading and unpacking the distribution to see if they have a parser generator or (as I strongly suspect) hand-rolled the parser
Don't you only have to write it once? You can put it in a function called map(f, old_list) ?
that doesn't really make it better if you end up writing or copying the function into every new project because you're not using luarocks (esp. for small things vs "real applications")
You don't need luarocks; it's one cp command to copy lume.lua into your project, and then you never have to update it. Most people are used to other ecosystems where there is a nontrivial cost to adding a library like this, but this simply isn't true in Lua.
That's nice if it works. I'm not doing much lua these days but for the majority of my time I couldn't use a lot of external stuff. I just looked it up, Lume at least existed in 2014. But between licenses and just having the 2nd file there it has been a chore. Maybe the map thing was indeed a bad example. Maybe I would have been a convert if Lume had existed in 2009ish.
if you like janet, what do you think of fennel? it's become my primary means of writing lua and i see no reason to go back.
Fennel is definitely an interesting way to make Lua more bearable, but unfortunately there are many issues it can’t fix, such as
Having looked briefly at the impact on several code bases, both private and open, I think the biggest incompatibility will be immutable for loop variables. It is very easy to fix (add local k = k in the loop) but mutating them was a frequent pattern. That's the main thing I had to change to add support for Lua 5.5 in LuaRocks for instance (https://github.com/luarocks/luarocks/pull/1844).
Nobody asked me, but I would think the way less weird change would be to rename the loop variable versus artificially shadowing it, and also serving as pseudo documentation as to why that is, e.g.
for ro_k, item in pairs(...) do
local k = ro_k
also, you have a typo in line 123 of your configure: s/5,4/5.4/
Thanks for the typo (fixed)!
Regarding renaming the variable, I would say it depends on the loop. Note that fixing existing code bases this way was suggested by the main author of Lua.
This PR is temporary anyway, because LuaRocks is written in Teal, which has different constraints from Lua and has not yet decided how to deal with this. It is possible that with the next version the old code will just work and be transparently translated to valid Lua 5.5 syntax.
came here to post exactly this! So happy with this release. The new global keyword is a welcome change.
How does the size of the language and the ease of embedding of Lua compare to JavaScript? I feel like they are quite similar in scope, but JavaScript is a language more people are gonna be familiar with.
The latest Lua spec is 71 pages, and the latest EcmaScript spec is 847 pages. I think they're similar in terms of level of specificity (i.e. how many questions you would run into if you tried to implement them) and page density, so I think that's a reasonably fair comparison. So JS is about 10x as complex as Lua.
What I know about the semantics of these languages matches that comparison. JS has a lot of really dark corners. For example, the spec specifies sorting behavior. Which you would think would just be some standard sorting algorithm, comparing the values with <. But no, it can't do that, that would be wrong. The trouble is that there are three totally innocent looking JS values a, b, c (integers and strings, no NaN involved) such that a < b and b < c and c < a. (The reason involves implicit string->number conversions and octal notation.) So the spec has to say how to work around that when sorting, since sort algorithms reasonably expect that if a < b and b < c then a < c.
Also "direct eval" vs. "indirect eval" in JS is fun. eval(s) behaves differently than const f = eval; f(s), because the spec says that the eval function should behave differently depending on whether it's called directly (using the name "eval"), or indirectly.
Lua is much smaller in terms of codebase and specification. One can easily understand all of the implementation of PUC-Lua, fully understanding a modern JS engine is not that easy. Also, Lua was made to be embedded from the start, that was the primary use case alongside its academic objectives at the uni.
Lua is almost Smalltalk (it calls things differently, but there is almost a 1:1 mapping from Lua to Smalltalk abstractions). Smalltalk was created as a bet that you could fully specify a language in one page of US Letter paper. JavaScript is a massive language.
There are some embedded JavaScript implementations that are similar size and speed to Lua (quickjs and DukTape). There are also some nearly-JavaScript things like Microvium that are much smaller than Lua.
My main reason for preferring Lua for embedding is Sol3, which makes it absolutely trivial to expose C++ objects to Lua (including using smart pointers or copies to manage lifetimes).
That's an interesting way to add global!
I don't completely understand it, played just a little bit with it, so may have misunderstood something.
Seems like the old code stays working but there's a way to opt-in into greater typo checking. Seems great.