Why do Lua arrays(tables) start at 1 instead of 0?

71,862

Solution 1

Lua is descended from Sol, a language designed for petroleum engineers with no formal training in computer programming. People not trained in computing think it is damned weird to start counting at zero. By adopting 1-based array and string indexing, the Lua designers avoided confounding the expectations of their first clients and sponsors.

Although I too found them weird at the beginning, I have learned to love 0-based arrays. But I get by OK with Lua's 1-based arrays, especially by using Lua's generic for loop and the ipairs operator—I can usually avoid worrying about just how arrays are indexed.

Solution 2

In Programming in Lua's first discussion of tables, they mention:

Since you can index a table with any value, you can start the indices of an array with any number that pleases you. However, it is customary in Lua to start arrays with 1 (and not with 0, as in C) and several facilities stick to this convention.

Later on, in the chapter on data structures, they say almost the same thing again: that Lua's built-in facilities assume 1-based indexing.

Anyway, there are a couple conveniences to using 1-based indexing. Namely, the # (length) operator: t[#t] access the last (numeric) index of the table, and t[#t+1] accesses 1 past the last index. To someone who hasn't already been exposed to 0-based indexing, #t+1 would be more intuitive to move past the end of a list. There's also Lua's for i = 1,#t construct, which I believe falls under the same category as the previous point that "1 to the length" can be more sensible than indexing "0 to the length minus 1".

But, if you can't break the mindset of 0-based indexing, then Lua's 1-based indexing can certainly be more of a hindrance. Ultimately, the authors wanted something that worked for them; and I'll admit I don't know what their original goal was, but it's probably changed since then.

Solution 3

My understanding is that it's that way just because the authors thought it would be a good way to do it, and after they rolled the language out to the public that decision calcified considerably. (I suspect there would be hell to pay were they to change it today!) I've never seen a particular justification beyond that.

Solution 4

Perhaps a less significant point, but one I haven't heard mentioned yet: there is better symmetry in the fact that the first and last characters in a string are at 1 and -1 respectively, instead of 0 and -1.

Solution 5

Lua libraries prefer to use indices which start at 1. However, you can use any index you want. You can use 0, you can use 1, you can use -5. It is even in their manual, which can be found at (https://www.lua.org/pil/11.1.html).

In fact, something cool here is internal lua libraries will treat SOME passed 0's as 1's. Just be cautious when using ipairs.
So that: ("abc"):sub(0,1) == "a" and ("abc"):sub(1,1) == "a" will be true.

 You can start an array at index 0, 1, or any other value:

-- creates an array with indices from -5 to 5
a = {}
for i=-5, 5 do
  a[i] = 0
end
Share:
71,862

Related videos on Youtube

Khaled Alshaya
Author by

Khaled Alshaya

I am member of the team responsible for the design, implementation and maintenance of the financial systems of the largest energy company in the world! If I could allocate some spare time, I spend it mostly on learning new technologies. C++ was the first programming language I learned and I still love using it for personal projects.

Updated on June 29, 2021

Comments

  • Khaled Alshaya
    Khaled Alshaya almost 3 years

    I don't understand the rationale behind the decision of this part of Lua. Why does indexing start at 1? I have read (as many others did) this great paper. It seems to me a strange corner of a language that is very pleasant to learn and program. Don't get me wrong, Lua is just great but there has to be an explanation somewhere. Most of what I found (on the web) is just saying the index starts at 1. Full stop.

    It would be very interesting to read what its designers said about the subject.

    Note that I am "very" beginner in Lua, I hope I am not missing something obvious about tables.

    • Ivan
      Ivan about 14 years
      The default scope is also global. The two biggest misfeatures of Lua.
    • BlueRaja - Danny Pflughoeft
      BlueRaja - Danny Pflughoeft about 14 years
      I would not call starting at 1 a misfeature. It actually makes more sense - programmers are just so well trained to think in terms of 0-based indexing from other languages that we don't like it. We are also trained to think 5/2 = 2. That doesn't make it right.
    • Norman Ramsey
      Norman Ramsey about 14 years
      It's interesting how many scripting languages have had default global scope, which I too think is the wrong default. But Icon has the same problem, and awk doesn't even provide a way to declare local variables except as surplus parameters. Scheme also has default global scope. @theatrus can you point to a scripting language with default local scope so we can see what are the consequences?
    • orlp
      orlp about 11 years
      @BlueRaja-DannyPflughoeft: no. Zero indexing makes more sense - humans are just so well trained in starting counting with 1 that languages that start with 0 are initially confusing. But I'd love to refer you to Edsger Dijkstra here: cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
    • BlueRaja - Danny Pflughoeft
      BlueRaja - Danny Pflughoeft about 11 years
      @nightcracker: When you count apples on a table, you count the first one as "one," the second one as "two," etc. Nobody counts the first one as "zero" and then adds one at the end; counting from zero is simply, unarguably, counter-intuitive. Yes, I realize that's how the indexing works internally, but that's why we call it an abstraction.
    • marcus
      marcus almost 11 years
      I never understood all the love towards 0-based indexing. It's nice for offsets (how many items to skip from the start?) and subsequences (0 ≤ x < n), but looks wrong for basic things (the second element is called one? The tenth element corresponds to index nine? WAT?). Even programmers count from 1 when they try to find a line reported by the compiler...
    • dualed
      dualed almost 11 years
      @NormanRamsey PHP has a default local scope. Make of it what you want :)
    • moteus
      moteus almost 11 years
      I think the main downside of 0-based indexing is that it is not consists with ffi interface. If you have ffi array you should use 0-based indexing, but when you use Lua array you should use 1-based. In other it is matter of taste.
    • Abhishek Avadhoot
      Abhishek Avadhoot over 8 years
      0 is correct if you care at all about modular arithmetic: m*n%n = 0.
    • thdoan
      thdoan over 8 years
      If you must, this is also valid: t = { [0] = "a" }; print(t[0])
    • Gianluca Ghettini
      Gianluca Ghettini almost 8 years
      An index is an offset from start, not the actual "label" of an item in a list. So the first element has offset 0 ence it's index is 0. Modular arithmetic, matrix multiplications, and many other algorithms are simpler if coded using the 0-index approach... make use of the Occam principle -> 0-index base is to be preferred (at least in a programming environment)
    • Gianluca Ghettini
      Gianluca Ghettini almost 8 years
      default scope is also global... which is like saying that a traffic light controller, in case of failure, commands all traffic lights to go green instead of red...
    • Ted Middleton
      Ted Middleton almost 8 years
      There are clearly advantages to 1- or 0- based indexing, but in Lua's case, 0- based would have been a better choice; look at Wireshark. Lua is used to extend large applications and expose internal data structures. Wireshark, for example, has to deal with lots of networking data structs, most of which use 0- based indexing (like the TCP segment field). Because those data structs already use 0- based indexing, it only makes sense for Wireshark's userdata types like Tvb, TvbRange, and ByteArray to use 0- based indexing. But then you have an awful mix of 0- and 1- based indexing.
    • Ted Middleton
      Ted Middleton almost 8 years
      If Lua's principal role in life wasn't interfacing and extending software written in other languages, I think 1- based indexing would be every bit as good as 0- based. As things are, though, 1- based indexing was a mistake.
    • Lake
      Lake over 7 years
      Just to share a point in favor of the 0-indexing, consider when iterating over array indices using modulus: int a[] = { 5, 7, 8, 3 }; for( int i=0; i<32; i++ ){ do something with a[i%4] } Very simple, compared to the ugly a[1 + i%4]
    • Leslie Krause
      Leslie Krause over 5 years
      The default global scope is intentional, and with good reason, because " without local declarations, you cannot say where the variable is local to." (RiciLake, Lua User's Wiki). But I'll agree, the 1-based indexing doesn't have nearly as good a rationale by comparison.
    • Charlim
      Charlim about 3 years
      People keep pointing to Dijkstra's argument in favour of counting from 0 to favour 0-based indexing, but his arguments are frankly terrible. He spends the first 3 paragraphs without mentioning counting from 0 at all, just to build up to "0 <= i < N looks a bit nicer than 1 <= i < N+1". His first 2 arguments in favour of convention a) aren't even relevant in the context of indexing. His argument about specifying ranges using only natural numbers presupposes that specifying a range that starts with 0 is desirable, which is circular with his ultimate conclusion.
    • Adam Tolley
      Adam Tolley almost 3 years
      zero-based indexing takes 5 minutes to get used to. one-based indexing is a lifetime of hassle when doing anything numerically related to the index.
  • Judge Maygarden
    Judge Maygarden about 14 years
    Possible justification: C only did it because an array is basically just a pointer and array[0] == array + 0;, and 1-based counting is more natural when array is really a hash table.
  • Alex
    Alex almost 14 years
    Lua indices are actually indices. In C when you say index what you really mean is an offset.
  • eonil
    eonil almost 14 years
    This is just a historical, marketing reason. No rational reason, especially at current time. And it seems even you're trying to avoid 1-based indexing instead of utilizing it :)
  • Dan D.
    Dan D. over 12 years
    @Eonil actually avoiding explicit indexing reduces indexing errors.
  • CodesInChaos
    CodesInChaos over 12 years
    @Eonil historic reasons are usually the relevant ones. You start with something, and then you can never change it, because it would break all existing code. Particularly bad for 0 vs. 1 indexing, since the way it breaks is pretty subtle.
  • CodesInChaos
    CodesInChaos over 12 years
    I don't get the concept of a table being valued 0. A table can have a length of 0. But that's independent of the choice of first index. I don't care about minor grammar mistakes, but I simply don't understand the point of your answer, which is why I downvoted.
  • Wesker
    Wesker over 12 years
    thats what i ment, a table cant be hold with a 0 index or value, since we use it as an empty table <,< when you have something this something its represented from 1,"n" so when you have nothing, your empty of something, wich leads us to a cero, but the cero dosnt count, lua its a lenguage that comes practical, you dont go outside and tell your friends you know what i have 0 songs of that artists, eigther you have some, or you dont. the point its table = {} thats cero an empty table
  • CodesInChaos
    CodesInChaos over 12 years
    An array that uses the index 0 as only element is still not empty. In fact lua supports this, it's just not the default convention.
  • Wesker
    Wesker over 12 years
    yup i agree with you, on some other lenguages, but not lua, lua index 0 dosnt exist, so we can imagine it like an empty = 0, or thats how i picture it, even when you can force the index to be 0, it wont work with the table values #table wont read a 0 index, so my answer its still that lua its basicly made like a regular event, now if they intend this or not its not really relevant you wont write the hole code again, and we cant do anything about it :/, i still belive that its fair to say that in lua an empty table has a 0 index
  • lhf
    lhf almost 12 years
    While this is nice, it was not the reason for starting at 1.
  • lhf
    lhf about 11 years
    Even if this is true, it is not at all relevant to how Lua was designed.
  • Felype
    Felype about 9 years
    The difference is between going from 1 to Length and from 0 to length -1, but in a for loop the < length is much more handy and easier to read on the "weirdo 0-based languages". I confess when I see a loop iterating from 1, i immediately assume it starts from the 2nd element :S
  • remram
    remram almost 4 years
    Is there a way to make ({'a', 'b'})[1] evaluate to 'b' not 'a' though? That seems built-in to me.
  • user2262111
    user2262111 almost 4 years
    ({[0] = 'a', 'b'})[1]
  • Timmmm
    Timmmm over 3 years
    That's not better symmetry. Now you have a situation where -3, -2, -1, 1, 2 and 3 are valid indices, but not 0!
  • Twisted Code
    Twisted Code about 3 years
    I thought it was the stupidest thing when I started playing around with it as part of a Minecraft mod called ComputerCraft, but given the historical precedent, I guess I can understand why it is the way it is. That said, do you happen to have a link handy where I can read more about this connection to Sol? I'm always curious about the background for a language I'm working with, even if I'm not using it for anything serious.
  • Twisted Code
    Twisted Code about 3 years
    how is it not better symmetry? Just because one index is completely invalid (doesn't point to either end, which I agree isn't great if you so happen to need EVERY index up to the integer limit... whatever that is for Lua) doesn't mean the symmetry isn't there
  • Twisted Code
    Twisted Code about 3 years
    yeah, no, this answer is highly suspect. Please provide a source for this statement about Portugal's legal system as it relates to Lua, as I'm not even close to seeing and understanding the relevance.
  • Twisted Code
    Twisted Code about 3 years
    I don't think you are getting negative rep for grammar. That's easy enough for people to edit to help you fix. The problem is your answer doesn't seem to be coherent even in its intent. What does the length of a table have to do with the choice of first index? That seems to be your entire argument: it's length equals its last index? If you ever come back to SO, you should take another look at this one. I'm sure after 10 years you'll understand why everyone was so hard on it. Sometimes I want to kick myself over answers I gave 5 years ago so... yeah
  • Norman Ramsey
    Norman Ramsey about 3 years
    There is a paper in the History of Programming Languages conference, and also lua.org/history.html
  • flarn2006
    flarn2006 almost 3 years
    That doesn't mean Lua needed to keep that particular aspect of Sol though.
  • BadZen
    BadZen almost 2 years
    There are no "arrays" in Lua, and so no choice about 0 vs 1 array "base index" was made during language design or implementation. At all. See my comment on the question for details.
  • BadZen
    BadZen almost 2 years
    -1 is not a valid array index in languages that have arrays (ie. not Lua). So the notion of "symmetry" between array indexes doesn't hold water.
  • BadZen
    BadZen almost 2 years
    Lua does not have one-based arrays. Lua does not have arrays. See above comment on the question.