News for hackers. Stuff that matters.
Re:Lua, a Misunderstood Language by mumblemumble on Friday January 15, 2021 @05:29PM (#25797383)
So, I don't do a lot of Lua programming - basically just having fun with Pico-8 on occasion - so I can't say I have a lot of experience with this. Every single other language I use starts at 0.

But what I have seen is that, starting from 1 felt weird to me for approximately 1 hour, tops. After that, it was no more or less of a switching challenge than switching between semicolon languages and non-semicolon languages. In other words, no big deal. And, once I got over it, I was pleasantly surprised to find out that I actually have fewer off-by-one errors in Lua than I do in other languages. Because the author is right: No matter how much professional experience I have starting with 0, starting with 1 is still the more innate way of thinking.

Also, my single biggest all time source of off by one errors is translating between mathematical notation and code in a 0-based language. That fact alone is cause for me to hope that Julia might one day supplant Python for data work.

Re:Lua, a Misunderstood Language by bilkow on Friday January 15, 2021 @06:33PM (#25798093)
You clearly have a different experience using 1-based index than me, it has caused me many off-by-one mistakes. Also, I almost never need to -1 with 0-based index, but in 1-based index its pretty common, specially if moving slices inside an array, the new index of the element is move_position + old_index - 1 (see example). Also see arguments by Djikstra [0].

Example:

  # python
  lov = ['l', 'o', 'v']
  o_index = 1;
  array = ['a', 'b', 'c', 'd', 'e', 'f']
  move_position = 3
  # elements moved here
  array = ['a', 'b', 'c', 'l', 'o', 'v']
  new_o_index = move_position + o_index
  print(array[new_o_index]) # prints 'o'

  -- lua
  local lov = { 'l', 'o', 'v' }
  local o_index = 2;
  local array = { 'a', 'b', 'c', 'd', 'e', 'f' }
  local move_position = 4
  -- elements moved here
  array = { 'a', 'b', 'c', 'l', 'o', 'v' }
  local new_o_index = move_position + o_index - 1
  print(array[new_o_index]) -- prints 'o'
Note that I'm not saying 0-based indexing is always absolutely better, but I generally prefer it and believe it usually makes more sense even outside of programming (including math), we're just not taught that way.

[0] https://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF transcript: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E...

Re:Lua, a Misunderstood Language by bsder on Friday January 15, 2021 @05:58PM (#25797685)
I'm glad that's true for you, but my personal experience suggests otherwise. Dijkstra also mentions the Mesa programming language which had all four of the conventions and that anything other than 0-based, half-open leads to errors. See: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E...

And for those claiming the world is 1-based, they're full of it. Machining measurement, for example, is ALL 0-based. We're talking a field that has multiple standards for everything and yet they converged on 0-based measurement.

The bigger problem, though, is that I even have to use array-based indexing to iterate something. That's just asking for bugs.

And, my favorite question for people who like 1-based is "Given index and length N, how do I create index-1?"

The answer, of course, is newindex = index - 1 % N.

The question is, of course, a trick because the answer is really: newindex = (index - 1) % N. Don't forget the parentheses or you have a bug.

Yeah, no. I'll stay in my 0-based languages thanks.

Side Note: I have other objections to Lua. The big one being that it's not really compatible between Lua installations. Everybody compiles different modules so Lua becomes neither small nor is it the same language between any two implementations.

Re:Lua, a Misunderstood Language by josephg on Friday January 15, 2021 @06:21PM (#25797963)
> my favorite question for people who like 1-based is "Given index and length N, how do I create index-1?"

Create index-1? I don't think I've ever needed do that. What does come up all the time in practice in both JS and Lua is "how do I assign past the current end of an array?"

In javascript (if you don't use .push) its arr[arr.length] = x

In Lua its arr[#arr + 1] = x

Even having worked with 0-based indexes for over 20 years, I still doubletake reading that javascript code when it’s embedded in complex code before I can convince myself its inserting. But the lua code is intuitive.

Likewise "read the last element in an array":

JS: arr[arr.length - 1]

Lua: arr[#arr]

I much prefer the lua version in all these cases.

And simplicity is important here because the code gets much worse when the array isn't in a local variable, but instead is some complex expression. confabulate(foo.bar.baz[foo.bar.baz.length - 1]); <-- Simple statement. Absolute mess.

Re:Lua, a Misunderstood Language by creata on Friday January 15, 2021 @07:17PM (#25798485)
> if you don't use .push

I don't think I've ever needed to avoid .push.

> I still doubletake

Why? "arr[i]" just means "skip i elements and get the next one," which is perfectly intuitive to me. I understand that familiarity is useful, but can you give an intuition for one-indexing that doesn't just appeal to what people are used to?

> the code gets much worse when the array... is some complex expression

Then... don't do that? Rust has "xs.last()", Python has "xs[-1]", and every language has variables. Anyway, even if that code is an "absolute mess" (which is a bit hyperbolic) it's hardly worse than the one-indexed equivalent, which would be

    confabulate(foo.bar.baz[foo.bar.baz.length]);
Re:Lua, a Misunderstood Language by josephg on Friday January 15, 2021 @08:26PM (#25798993)

    confabulate(foo.bar.baz[foo.bar.baz.length]);
The problem I have is that at a glance this looks correct. Even after decades of programming, I would scroll right past this line in JS without noticing the off-by-1 error here. The only saving grace is that this error will occur consistently.

But yes, I'd take Rust's xs.last() in a heartbeat. Especially because you can assign through it with last_mut().

That said, I agree with others in this thread. People fixate on the 1 based indexing of lua but you get used to it pretty quickly once you spend time with the language. Lua's real problem is its sparse standard library and its weak package ecosystem. If history had run its course slightly differently, I could easily see lua ending up inside web browsers instead of javascript. And becoming much more popular as a result. Lua and javascript are remarkably similar languages semantically.

Re:Lua, a Misunderstood Language by samatman on Friday January 15, 2021 @06:20PM (#25797945)
> The bigger problem, though, is that I even have to use array-based indexing to iterate something. That's just asking for bugs.

You absolutely do not, the standard Lua idiom is to use ipairs. The numeric for loop is there, of course, and the index of the pair (index, value) returned by ipairs will be 1 based. of course.

Iteration isn't why 1-based indexing is bad, it really shows its inadequacy when doing interval maths. I make abstract syntax trees in Lua, and a node in that tree with zero width at the 4th position is { left = 4, right = 3 } which is... awful.

Re:Lua, a Misunderstood Language by robscallsign on Friday January 15, 2021 @08:03PM (#25798816)
> And for those claiming the world is 1-based, they're full of it.

I just did an N=1 experiment with my two children, aged 4 and 6. I held up a single apple in my hand, and asked them how many apples I was holding.

They said 1.

Re:Lua, a Misunderstood Language by bsder on Friday January 15, 2021 @08:21PM (#25798960)
Except that your children are >1460 days old and >2190 days old.

You count age from 0 in most English-speaking countries (there are places where "1 year old" means 0<=x<365 days old). When you are less than 1, we count with smaller units.

So, my N=3 sample (you and your two children) says we use 0-based counting.

Thank you for making my point. :)

Re:Lua, a Misunderstood Language by robscallsign on Friday January 15, 2021 @08:49PM (#25799121)
That's because I use round(age) when referring to their floating point age in conversation like any sane person.
Re:Lua, a Misunderstood Language by bsder on Saturday January 16, 2021 @01:53AM (#25800623)
Round(age)? So, they became one year old at 180 days? I doubt that.

And, as I pointed out, there are folks in the world who call their newborn "one year old". And they consider themselves quite sane, thanks.

They count from 1. We count from zero.

Back to the original issue ...

The problem you now have in programming is that it isn't enough that basing from 1 is equivalent. The vast majority of the programming world has converged on 0-based. 1-based has to demonstrate that it is better in order to compensate for the friction of existing in a 0-based world.

And 1-based simply isn't demonstrably better even if I concede that it isn't worse (and I do not concede that).

Re:Lua, a Misunderstood Language by snarfy on Friday January 15, 2021 @06:52PM (#25798256)
It made a lot more sense to me once I fixed the terminology.

You keep saying index, but what you are referring to is an offset.

Re:Lua, a Misunderstood Language by LgWoodenBadger on Friday January 15, 2021 @06:57PM (#25798293)
Measuring and counting seem to be two fundamental things in this context.
Re:Lua, a Misunderstood Language by necovek on Friday January 15, 2021 @07:32PM (#25798593)
I generally agree there are benefits to both, but even the author uses a bad example. They talk of a baby becoming one year old after one full Earth revolution, but do not acknowledge that baby is basically 0 years old until that time. Sure, we'd say it's in its first year, but age-in-years is zero-based.

Part of this is using counting numbers for continuous values, part of it is philosophical, but there are a lot of mathematical properties of zero that make it really appealing (eg. being zero-based allows Python to have a very clear iterable[-1] interpretation).

Re:Lua, a Misunderstood Language by hisham_hm on Friday January 15, 2021 @07:55PM (#25798767)
The Lua standard library also uses -1 to mean "last element" in various functions; never found it to be an issue. In fact, it feels quite symmetric, going 1,2,3 from one side and -1,-2,-3 from the other.
Re:Lua, a Misunderstood Language by necovek on Friday January 15, 2021 @08:30PM (#25799021)
So is l[len(l) - 1] == l[-1] in those contexts?

Potential for one-offs is always there, but I am highlighting how _most_ of the math is simplified when there is a zero between positive and negative numbers :)

Re:Lua, a Misunderstood Language by hisham_hm on Friday January 15, 2021 @09:08PM (#25799258)
> So is l[len(l) - 1] == l[-1] in those contexts?

No, because Lua is 1-based :) The last element is l[#l] (#l is "length of l"). Negative indices aren't really used in arrays, but are used in the string library, so given s = "hello"; s:sub(1,4) gives you "hell" and s:sub(-2,-1) gives you "lo".

Re:Lua, a Misunderstood Language by necovek on Saturday January 16, 2021 @03:25AM (#25800937)
Sure, that was my point: s:sub(#s-2,#s-1) != s:sub(-2,-1) — if # works on s at all :)

Basically, some things are more "natural" with 1-based counting, but some aren't.

Re:Lua, a Misunderstood Language by hisham_hm on Monday January 18, 2021 @01:42PM (#25824995)
> Sure, that was my point: s:sub(#s-2,#s-1) != s:sub(-2,-1) — if # works on s at all :)

And why would they ever be the same? Writing "#s-2" you're treating -2 as a relative _offset_, not an index.

> Basically, some things are more "natural" with 1-based counting, but some aren't.

Yes, offsets are naturally zero-based, and indices (everywhere other than languages derived from the C tradition) are naturally 1-based. The reason why C and its descendants use zero-based indexes is because C mixes indexes with offsets (since offsets are the low-level primitive in machine language), so that given a pointer p, we have that p[i] and p+i are the same.

If instead C had not done that and used 1-based indexing like everyone else back then, I'm sure people today would be claiming how C is superior for providing both 1-based indexing with [] and 0-based offsets with +, since there are always scenarios where one leads to more natural expressions that the other, and how people mixing them up were clearly not suited for the subtleties of low-level programming in C, and should be instead using simpler languages with garbage collection and without pointer arithmetic. :)

Re:Lua, a Misunderstood Language by xscott on Friday January 15, 2021 @09:37PM (#25799445)
> Also, my single biggest all time source of off by one errors is translating between mathematical notation and code in a 0-based language.

If you were working with polynomial coefficients, Fast Fourier Transforms and convolutions, or modulo arithmetic, you'd prefer zero based arrays. In my experience, the majority of places where math notation uses 1-based arrays are in applications where the index doesn't matter.

I prefer zero based arrays specifically because they are better for doing mathematics. Yeah, it sucks that a lot of matrix algorithms in text books use one based arrays, but I blame the text book for getting it wrong.