17

I have an issue with Lua. It uses one-based indexing. The language has a feature to set value at index 0, but the value won't be counted as a part of table length, and string manipulations are still one-based. Therefore, I think the feature is something special rather than about indexing.

I don't want a flame about one-based or zero based. I'm just asking is there a feature to force zero-based indexing.

eonil
  • 83,476
  • 81
  • 317
  • 516
  • 1
    Could I just ask why it's an issue? Ok, so you prefer 0-indexing, but why can't you work with 1-indexing? – gnud Aug 07 '10 at 13:22
  • 5
    I have this issue too :) Regardless of what makes sense I get this wrong in lua almost every single time. I got so used to working with other languages that are zero based that my lua code is full of bugs due to this one thing alone! – jcoder Aug 07 '10 at 13:46
  • i don't think there is some flag that would switch lua from 1 to 0 and as such other than modifying lua which require use of a non-standard lua (i here dub lua0) i don't see how it would be done – Dan D. Aug 07 '10 at 13:56
  • @gnud This is clearly an issue because it's script for C, not for XPath. Of course I can work with 1-indexing, but it's too inefficient for me because I'm dumb as I feel hard about using dual indexing system at once. (I have to use C for host system) And any indexing data interchanging between script and host must be translated. I can sure this will cause more bugs which I feel harder to handle. – eonil Aug 07 '10 at 14:12
  • @JB That's the what I'm saying. 1-indexing language is not naturally integrated with 0-indexing languages. – eonil Aug 07 '10 at 14:15
  • possible duplicate of [Why do Lua arrays(tables) start at 1 instead of 0?](http://stackoverflow.com/questions/2785704/why-do-lua-arraystables-start-at-1-instead-of-0) – Judge Maygarden Aug 07 '10 at 14:56
  • 2
    @Judge I think it's different question because I asked a way to change default behavior of the language, and the question is asking rational reason of the language design. – eonil Aug 07 '10 at 15:28

10 Answers10

9

Working with 0-indexed arrays is actually pretty simple:

local array={
[0]="zero",
    "one",
    "two"
}

for i=0,#array do
    print(array[i])
end

You can use #array without subtracting 1 because the length operator actually returns the highest index (technically, the key before the first nil), not the actual "length" (which wouldn't make sense in Lua anyway).

For string operators, you'll probably have to just create duplicate functions (though there might be a better way)

ipairs() also only supports 1 indexing, so you'll have to define your own function or just use a regular for instead.

12Me21
  • 992
  • 10
  • 22
4

I know this question is already 1 year old, but I thought future seekers would be interested in the fact, that CFF Explorer contains a scripting language (Lua with patches), which has 0-indexed table patch:

http://www.ntcore.com/files/cffscriptv2.htm

Also, in the document above, the author stated that he had to disable most of the standard library functions, because they're incompatible with 0-indexed arrays, so please reiterate your thought process about this issue :)

antekone
  • 41
  • 2
3

The direct answer: Modify the source code of Lua. Change all the operations on lua table to base-0.

Here I'm doing it, along with Lua standard library. Windows binary available.

http://lua-users.org/wiki/CountingFromOne (some comment at the bottom)

https://github.com/farteryhr/lua-base-0 (see the commit history for what have been modified)

Mostly dirty work about +1 -1, and most of them have been done.

Please write some test cases (covering as many details of the language as possible) and report bugs.

(For now it's known there's still something wrong with metatable, but I can't find time to investigate it)

  • 1
    This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/low-quality-posts/22474278) – Dave Mar 15 '19 at 10:51
  • @Dave Thanks for your advice and I've added a direct answer. Please consider removing the down vote. – Farter Yang Mar 15 '19 at 11:00
  • My comment has/had nothing to do with voting on the answer. There is no way to determine who cast votes. – Dave Mar 15 '19 at 11:01
  • Maybe, I mean, the review of recommend deletion? – Farter Yang Mar 15 '19 at 11:19
2

I think that that Lua already has the feature that you need to make it 0-based. Unfortunately the feature that I refer to is Lua's open source license.

I was unable to find a patch or fork of Lua that changed the 1-based nature of the language.

Unfortunately forking Lua to change it to 0-based would also break backwards compatibility. Loss of all the current add-on modules may be too great a price to pay for ease of use.

Michael Mior
  • 28,107
  • 9
  • 89
  • 113
gwell
  • 2,695
  • 20
  • 20
2

Eonil's comment to ponzao's answer: Real problem is base language should be the C which is 0-based indexing language. Indexing data interchanging between script and host must be correctly translated.

If you want to expose C data structures to Lua, use userdata to package them up. You can make the indexing behave however you like with these using metatables. This way, you can ensure correct translation.

Charles Stewart
  • 11,661
  • 4
  • 46
  • 85
1

Dirty approach with some drawbacks:

function zeroIndexed(tbl)
    local mt = {}
    mt.data = tbl
    mt.__index = function(t, k)
        return mt.data[(type(k) == "number" and k + 1 or k)]
    end
    mt.__newindex = function(t, k, v)
        mt.data[(type(k) == "number" and k + 1 or k)] = v
    end
    mt.__len = function()
        return #mt.data
    end
    return setmetatable({}, mt)
end
t = zeroIndexed({5, 6, 7})
print(t[0], t[1], t[2])
t[0] = 4
print(t[0], #t)
t[#t] = 8
print(t[#t - 1], #t)

Lua 5.2 outputs:

5       6       7
4       3
8       4

In Lua 5.1 #t returns 0 because the __len metamethod isn't respected for tables and strings.

But remember that table.insert and other table methods won't work here anymore because inserting is now done via t[#t] = x.

I don't recommend using this.

vince
  • 11
  • 1
  • 2
1

Even if there was a #define TABLE_START_INDEX 1 in the Lua sources (which I don't believe there is) you would pretty much shoot yourself in the leg by changing this. This is due to most libraries using 1-based indexing. Thus any code doing something like the following would break.

for i = 1, #t do ... end

You can of course use iterators or even create helper functions to avoid this.

function get_first(t) return t[1] end

Probably though the actual problem you are trying to solve is harder than changing from 0 to 1-based indexing.

ponzao
  • 20,684
  • 3
  • 41
  • 58
  • 4
    Nope. It's not a real problem. Real problem is base language should be the C which is 0-based indexing language. Indexing data interchanging between script and host must be correctly translated. And I have to handle dual indexing system at once always. – eonil Aug 07 '10 at 14:22
0

You can fix this lua-flaw by using an iterator that is aware of different index bases:

function iarray(a)
  local n = 0
  local s = #a
  if a[0] ~= nil then
    n = -1
  end
  return function()
    n = n + 1
    if n <= s then return n,a[n] end
  end
end

However, you still have to add the zeroth element manually:

Usage example:

myArray = {1,2,3,4,5}
myArray[0] = 0
for _,e in iarray(myArray) do
  -- do something with element e
end
rhavin
  • 1,512
  • 1
  • 12
  • 33
-3

I've found when interfacing with a 0 indexed language (C for example) it is easiest to just not use index 0. It is wasteful of memory, but changing lua is pretty absurd.

-3

the answer to your questuion its no, theres no way to force all the process that lua handles with an index 0, because right now as far as i know #table goes from 1,"n" and without it index 0 its pretty much useless, at my sight, but depends what you want to do, you could compare if you have something or not, from to tables, 1 that reads the products, 1 that reads the income, and if products increase you have more, if products are = 1 then you have nil, so you just read 1 table, rather than 2, i hope i make my self clear <,<

Wesker
  • 231
  • 1
  • 3
  • 10