News for hackers. Stuff that matters.
Re:I open sourced my game along with a tutorial on how to ma... by shakna on Sunday July 05, 2020 @09:15PM (#23743754)
Once you get used to it, it does help prevent a whole bunch of off by one errors though, as you don't need math when grabbing a range.

Like a string will always be:

    s:sub(1, #s)
And a sequence table will always be:

    for i = 1, #t do
      t[i]
    end
Re:I open sourced my game along with a tutorial on how to ma... by anonymoushn on Sunday July 05, 2020 @09:48PM (#23743908)
I disagree. Particularly when parsing strings, it's useful if the upper bound of one substring is the lower bound of a nonoverlapping substring immediately after. For example, here's a routine to split a string into the part before the first dot and the part after:

  function split_dot(s)
    local idx = s:find(".", 1, true)
    if not idx then return s end
    return s:sub(1,idx-1), s:sub(idx+1)
  end
It may come as a surprise that one should use a difference of 2 to skip over one character!

In a language that used the half-open interval convention we would end up with:

  s:sub(0, #s)
and

  for i = 0, #t do
    t[i]
  end
which seem just as good to me.
Re:I open sourced my game along with a tutorial on how to ma... by DarkWiiPlayer on Monday July 06, 2020 @07:14AM (#23746646)
> It may come as a surprise that one should use a difference of 2 to skip over one character!

On the contrary; unless you're very used to offset-indexing, it seems more natural to start at the next element for the next substring, or the 2nd next element when skipping one.

Re:I open sourced my game along with a tutorial on how to ma... by shakna on Sunday July 05, 2020 @10:57PM (#23744249)
You wouldn't end up with this:

     s:sub(0, #s)
You would end up with:

     s:sub(0, #s - 1)
Which demonstrates the off-by-one error.
Re:I open sourced my game along with a tutorial on how to ma... by anonymoushn on Monday July 06, 2020 @12:13AM (#23744630)
Can you explain what the intent of the code is and what the error is? It looks like the original code just grabs a substring containing the entire string. If the language used half-open intervals with an exclusive upper bound, the code I posted would also do that.

In python, for example, the operation of copying a list can be correctly written l[0:len(l)]. You're more likely to see l[::] or list(l) though.

Edit: I think maybe the proposed error that's being avoided is "a user tries to use a closed interval when sub takes a half-open interval." It seems like the opposite error is similarly likely though. Some areas where it's nice to have half-open intervals like using a modulus to restrict a value to an interval or parsing strings don't have such a symmetry.

Notably if you're making a binary heap the formulas come out much nicer with 1-indexing than with 0-indexing, but I haven't met any other examples where this is the case.

Re:I open sourced my game along with a tutorial on how to ma... by shakna on Monday July 06, 2020 @01:18AM (#23744941)
If the language is using an exclusive upper bound, then it is correcting the mistake of the programmer for specifying a length beyond what the string contains.

Lua does do that, so in this theoretical world with 0-indexed strings, it would still work as expected.

But it doesn't change the fact that you're not actually specifying the right length - the language is correcting an off-by-one error, which means that the programmer's mental model is probably going to be wrong, and it will bite them when they don't expect it to.

That's what off-by-one errors are - a place where the programmer's mental model doesn't actually fit the real world. It is better to not introduce places where they can happen in the first place, rather than to complicate things with edge cases where sometimes it works and sometimes it doesn't.

Re:I open sourced my game along with a tutorial on how to ma... by dragonwriter on Monday July 06, 2020 @01:48AM (#23745075)
> If the language is using an exclusive upper bound, then it is correcting the mistake of the programmer for specifying a length beyond what the string contains.

No, it's not-correcting the not-error of the programmer specifying the correct upper bound using the half-open-interval model, a common mathematical model of range specification that has lots of useful properties.

Re:I open sourced my game along with a tutorial on how to ma... by anonymoushn on Monday July 06, 2020 @02:44AM (#23745319)
It's useful, if you are writing ternary search (over integers) or some such thing concerned with intervals, to be able to compute the length as hi-lo, and to be able to use hi<lo to check whether an interval is malformed, rather than writing hi-lo+1 and hi+1<lo. In the example about using modulo to place all integers into some interval upthread, most programming languages let you write (n-lo)%(hi-lo)+lo, but in Lua you should maybe write (n-lo)%(hi+1-lo)+lo. It doesn't seem like I am getting less likely to make errors here!
Re:I open sourced my game along with a tutorial on how to ma... by sergeykish on Monday July 06, 2020 @09:58AM (#23747887)
That would be strange, in Ruby

    s = "foo"
    s.length
    #=> 3
    s[0, s.length]
    #=> "foo"
Same in JavaScript

    s.slice(0, s.length)
and Python

    s[0:len(s)]
Re:I open sourced my game along with a tutorial on how to ma... by shakna on Monday July 06, 2020 @01:40PM (#23750435)
Yet, none of those are consistent with that on non-string objects:

To get the last object of an array in JS is:

    arr = [1, 2, 3]
    arr[arr.length - 1]
To get the last object of an array in Python is:

    arr = [1, 2, 3]
    arr[len(arr) - 1]
To get the last object of an array in Lua is:

    arr = {1, 2, 3}
    arr[#arr]
Re:I open sourced my game along with a tutorial on how to ma... by sergeykish on Monday July 06, 2020 @05:34PM (#23753045)
There is a difference between order and offset, both consistent and makes sense. We use both models in everyday life. Examples of offset are ruler (marks 0, 1, ...), time offset (this hour, next hour, ..), age (newborn, one year, two years), count (last, last but one). That's reflected in our languages [1].

> non-string objects

There is no difference between array and string access in ruby, python, js.

There are better ways to access last element (python, ruby):

    >>> arr[-1] # meaning first element from back (1-indexing!)
    3
I mentioned your comment is wrong. I do not know why you are turning it into 0-indexing vs 1-indexing, looks like changing topic for me.

[1] https://en.wikipedia.org/wiki/Comparison_of_programming_lang...

Re:I open sourced my game along with a tutorial on how to ma... by shakna on Tuesday July 07, 2020 @03:32AM (#23756619)
> I mentioned your comment is wrong. I do not know why you are turning it into 0-indexing vs 1-indexing, looks like changing topic for me.

... That's exactly where this topic started:

> 1-index kept throwing me off though

---

> There is no difference between array and string access in ruby, python, js.

There's no difference in Lua either:

    s:sub(1, 1)
    tbl:select(1, 1)
But it doesn't use offset, and I find that more useful for preventing off-by-one errors.
Re:I open sourced my game along with a tutorial on how to ma... by sergeykish on Tuesday July 07, 2020 @05:21AM (#23757235)
I am to used to 0-indexing to judge. If it is not clear already - I am not going to participate in who is better. My thread is

>>>> a string will always be:

    s:sub(1, #s)
>>> In a language that used the half-open interval convention we would end up with:

    s:sub(0, #s)
>> You would end up with:

     s:sub(0, #s - 1)
> That would be strange, in Ruby

    s[0, s.length]
Your argument against 0-index is just plain wrong. No one creates such API. It would be to awkward - either #s should be `length + 1` or `sub` should expect `length + 1`.

----

>>>> Once you get used to it, ... you don't need math when grabbing a range.

I assure you once you get used to 0-indexing there is no need for math when grabbing a range

    s[0..s.length] # that is identity through range in ruby 
----

>>>>> 1-index kept throwing me off though

>>>> it does help prevent a whole bunch of off by one errors

You claim superiority, it is not. I can't remember such errors in my life. It may be easier to describe to children but I doubt it. My first encounter with 0-indexing was with ruler - "why it starts with 0?" - pre-school. I can claim 0-index is natural. I would not.

There is no better model just "happy accidents".

Re:I open sourced my game along with a tutorial on how to ma... by DarkWiiPlayer on Monday July 06, 2020 @07:15AM (#23746654)
unless the fantasy-lua went all the way and `#` returned the offset of the last element, that is, the length minus one