I had to open the desktop app to write this because I could never write a rant this long on the app.

This will be a well-informed rebuttal to the "arrays start at 1 in Lua" complaint. If you have ever said or thought that, I guarantee you will learn a lot from this rant and probably enjoy it quite a bit as well.

Just a tiny bit of background information on me: I have a very intimate understanding of Lua and its c API. I have used this language for years and love it dearly.


"arrays start at 1 in Lua" is factually incorrect because Lua does not have arrays. From their documentation, section 11.1 ("Arrays"), "We implement arrays in Lua simply by indexing tables with integers."

From chapter 2 of the Lua docs, we know there are only 8 types of data in Lua: nil, boolean, number, string, userdata, function, thread, and table

The only unfamiliar thing here might be userdata. "A userdatum offers a raw memory area with no predefined operations in Lua" (section 26.1). Essentially, it's for the API to interact with Lua scripts. The point is, this isn't a fancy term for array.

The misinformation comes from the table type. Let's first explore, at a low level, what an array is. An array, in programming, is a collection of data items all in a line in memory (The OS may not actually put them in a line, but they act as if they are). In most syntaxes, you access an array element similar to:


Let's look at c, so we have some solid reference. "array" would be the name of the array, but what it really does is keep track of the starting location in memory of the array. Memory in computers acts like a number. In a very basic sense, the first sector of your RAM is memory location (referred to as an address) 0. "array" would be, for example, address 543745. This is where your data starts. Arrays can only be made up of one type, this is so that each element in that array is EXACTLY the same size. So, this is how indexing an array works. If you know where your array starts, and you know how large each element is, you can find the 6th element by starting at the start of they array and adding 6 times the size of the data in that array.

Tables are incredibly different. The elements of a table are NOT in a line in memory; they're all over the place depending on when you created them (and a lot of other things). Therefore, an array-style index is useless, because you cannot apply the above formula. In the case of a table, you need to perform a lookup: search through all of the elements in the table to find the right one. In Lua, you can do:

a = {1, 5, 9};
a["hello_world"] = "whatever";

a is a table with the length of 4 (the 4th element is "hello_world" with value "whatever"), but a[4] is nil because even though there are 4 items in the table, it looks for something "named" 4, not the 4th element of the table.

This is the difference between indexing and lookups. But you may say,

"Algo! If I do this:

a = {"first", "second", "third"};

...then "first" appears in my console!"

Yes, that's correct, in terms of computer science. Lua, because it is a nice language, makes keys in tables optional by automatically giving them an integer value key. This starts at 1. Why? Lets look at that formula for arrays again:

Given array "arr", size of data type "sz", and index "i", find the desired element ("el"):

el = arr + (sz * i)

This NEEDS to start at 0 and not 1 because otherwise, "sz" would always be added to the start address of the array and the first element would ALWAYS be skipped. But in tables, this is not the case, because tables do not have a defined data type size, and this formula is never used. This is why actual arrays are incredibly performant no matter the size, and the larger a table gets, the slower it is.

That felt good to get off my chest. Yes, Lua could start the auto-key at 0, but that might confuse people into thinking tables are arrays... well, I guess there's no avoiding that either way.

  • 2
  • 13
    Nice rant with a lot of information well explained

    Some minor nitpicking: to access the sixth element of an array you would add five times the size of a single element to the base address
  • 3
    @korrat Correct, that's a good point. I appreciate you reading the information attentively enough to find that :)
  • 3
    @AlexDeLarge I know you appreciate when people have specific reasons for disliking JS. This is one of them for me, and one of the reasons I love Lua so much more. JS pretends that it has arrays, and even has a structure named Array, while Lua doesn't lie to you and never even bothered implementing arrays, which by definition, they cannot.

    Of course, this is a very minor reason, but I thought you might appreciate the informed argument.
  • 0
    @namenlossss I disagree that the code is less clean. The idea is you would never access data from a table by index. Using the pairs() function is the way to go, because if you go by index, you will miss anything that doesn't use an integer as a key.

    It's just a different environment. One that I admire.
  • 0
    @namenlossss Habits are a dangerous... habit
  • 0
    I still feel like they could start the index at 0 though... Sure, it's not an "array" but in programming we start counting at 0.
  • 2
    TL;DR lua arrays are lists

    I hope i understood it propely 😁
  • 1
    @olback No, there's an important distinction... we do NOT start counting at 0, we start indexing at 1. Because of the formula I mentioned, not just because its "cool" and "techy". An automatic key is a count. Not an index.
  • 2
    This is my favorite rant of all time. You did an amazing job explaining this my dude. Really interesting.
  • 1
  • 2
    Just wanted to get back at op and say: i am now more in love with Lua. Thanks man!
  • 0
    @AleCx04 God, I love Lua so much.
Add Comment