I'm not the OP, but for me it's the absolutely braindead design decisions around arrays, respectively the lack thereof. Arrays (or lists, vectors, sequences, whatever) are such a fundamental concept that not supporting them directly is inexcusable in my opinion, and very annoying in practice. You can abuse tables (i.e., hashmaps) as arrays, but they exhibit very strange behavior and footguns. For example (keep in mind that #a is supposed to return the length of a table-abused-as-an-array):
> a = {}
> a[1] = "x"
> a[2] = "y"
> a[3] = "z"
> #a
3 -- okay
> a[2] = nil
> #a
1 -- wat
> a[4] = "w"
> #a
4 -- wat
> a[2] = nil
> #a
4 -- okay (I guess)
> a[4] = nil
> #a
1 -- wat
You can't just print a table, it will only display its memory address – you'll have to write that function yourself. Considering that tables are the fundamental non-scalar datastructure in Lua, and Lua is supposed to be a scripting language with a REPL, this is mind-boggling.
Oh, and a table doesn't keep track of the number of its elements, you have to manually iterate over all elements and count them because of ... reasons?
Exactly – unintuitive, inconsistent behavior like this is why I wrote "braindead design decisions around arrays". I know of no other language that managed to get something as simple as arrays quite as wrong as Lua did.
it's a bit of a disingenuous example because it ignores the existence of table.remove, which removes an index and reshuffles the indices to maintain the array.
you can also swap and pop using the magic of multi assignment to preserve index order if you don't care about maintaining value order:
a[1], a[#a] = a[#a], nil
If you do care about value order there's table.sort
Just because you don't like the raw behavior doesn't mean it's incorrect. You can make the same argument about other languages in a practical use case
I'm a PHP dev and I would never rely on setting an array index to null or calling unset() on a collection if I'm deleting an element. Both lead to bugs. In the former case, null is treated as a set value so the count is inaccurate. In the latter case, the count is correct but the indices aren't continuous any more. JS has the same behavior with null and delete. Both PHP and JS have functions for manipulating arrays just as lua does.
One way to think about "tables" is that they have an array part and a hashmap part. The # operator works on the array part simply starts counting from the first index and stops counting when it reaches nil.
Your complaints sound a little bit like you wish Lua was a little bit more, but it kind of has a design goal of being simple language you can embed. You are meant to bring your own batteries.
> One way to think about "tables" is that they have an array part and a hashmap part.
But why conflate the two? There's no benefit to this, only drawbacks.
> The # operator works on the array part simply starts counting from the first index and stops counting when it reaches nil.
That's obviously not the case, as can be seen from #a returning 4 after setting a[4] = "w", even though a[2] == nil. There's no simple logic behind the # operator's behavior, it's an unintuitive mess.
> Your complaints sound a little bit like you wish Lua was a little bit more, but it kind of has a design goal of being simple language you can embed.
No, a simple language doesn't have to be inconsistent.
> No, a simple language doesn't have to be inconsistent.
Sorry I meant to say minimal and I was referring to the lack of certain features , not necessarily simple which is something else.
> That's obviously not the case, as can be seen from #a returning 4 after setting a[4] = "w", even though a[2] == nil. There's no simple logic behind the # operator's behavior, it's an unintuitive mess.
Oh, so perhaps it's a combination of being an "unintuitive mess" and/or it's been changed and/or I don't even remember.
Running the code you provided in the Lua online demo (which is lua 5.4.6) yields 3,3,4,4,3 so I guess you were running an older version.
I don't think this is a big problem in practice if you are just aware of this. It's a bit like 1 vs 0 based indexing. It may have been a problem in the beginning but it's been too long since I first started using Lua. And here you'd have a point.
> But why conflate the two? There's no benefit to this, only drawbacks.
I honestly don't know. I'm actually more on your side when it comes to distinguishing arrays and tables. I just don't think it's as big of a deal as you make it out to be.
-
As I alluded to earlier, you can just change Lua to fit your needs. It's meant as a language you embed in your own framework and was never really meant as a fully standalone language as far as I understand. Its position of being standalone is kinda weak in my opinion.
You even mentioned previously that "Lua is supposed to be a scripting language with a REPL" but the REPL included is the bare minimum.
By far my own biggest "complaint" about Lua is that it's dynamic. However Lua with types would be a different language entirely.