Using vec2 as a table index

I’d like to use vec2 variables as table indexes, but I am having a hard time getting back to the original table entries. For example…

my_table = {}
my_table[ vec2(1,1) ] = "foo"
print( my_table[ vec2(1,1) ] )

…results in “nil” being printed instead of “foo”.

And yet…

print( vec2(1,1) == vec2(1,1) )

…results in “true” so it appears that these two are equal in Lua.

Why won’t the table indexing work?

Is there a solution other than using tostring(vec2(1,1))? I’d rather not use tostring() because it drastically slows down the generation and retrieval from the table.

I assume you are indexing a two-dimensional grid of some sort?

You’re probably better off with a nested table or a packed list…

Two dimensions: row[y].column[x]

Packed: item[y*width + x]

I

vec2 is a special class; I’d avoid trying to index those. While it’s syntactically valid, it’s certainly too confusing to debug. Best off packing as @tomxp411 mentions.

If you are married to two parameters, try it with my_table[“1,1”]; cheat; make it into a string that has your parameters.

@efc Maybe something like this.


function setup()
    newTab={}
    
    -- create entries
    createTab(newTab,vec2(1,2),12)
    createTab(newTab,vec2(3,5),35)
    createTab(newTab,vec2(2,3),23)
    createTab(newTab,vec2(2,1),21)
    createTab(newTab,vec2(1,4),14)
    
    -- show entries
    for a,b in pairs(newTab) do
        if type(b)=="table" then
            for c,d in pairs(b) do
                print(d)
            end
        end
    end
end

-- create table
function createTab(tab,v2,val)
    if tab[v2.x]==nil then
        tab[v2.x]={}
    end
    tab[v2.x][v2.y]=val
end

The packing strategy works, and is faster than tostring, thanks @tomxp411.

I still wonder about the mysteries of vec2, but I’ll believe @aciolino that I just don’t want to go there!

When two vec2s are tested for equality then Codea is smart: it tests the values. So vec2(1,1) == vec2(1,1) is true, but the two are different objects. When used as table indices then Codea isn’t smart and just uses the object, so then the two different vec2(1,1)s are different.

Thanks @Andrew_Stacey, that explains the behavior I am seeing, although it is confusing. It might be cleaner to not cheat on the equality test and provide a function vec2.same( v1, v2 ) that returned a boolean. This would remind everyone that vec2s are objects, not really “types”.

It also reminds me that in some situations where I really won’t be using the vec2 features, I might be better off avoiding the creation of the object altogether to avoid the overhead. Food for thought, certainly.

By the way, while digging into this I found the vector documention in Codea itself, but that information is missing from the reference area on this website.

@efc Of all the times when I compare vec2 objects, I can’t think of any where I don’t want true vector equality so I think that Codea gets it right with that one. Rather, I think that using strange indices in a table should be regarded as the abhorrent behaviour here!

@efc actually, all objects are an instance of a type. =)

However, vec2 is a compound type - since it has more than one value (.x and .y). I don’t think that Lua uses comparison operators to locate table entries. I think it uses a hash table, which doesn’t use comparisons. So my guess is that the reference is being hashed, not the value.

Of course, I could be wrong… my assumptions about Lua have been smashed in here more than once already. =)

@efc concerning your first result and question:

results in “nil” being printed instead of “foo”.

The explanation is that (i think):

my_table[ vec2(1,1) ] = "foo" will use the resulting object adress of vec2(1,1) to index ‘foo’.
But the next line, when you call print( my_table[ vec2(1,1) ] ) you are looking at the index corresponding to a new instance of vec2, which has a different adress from the first instance of vec2 you used for foo. This new adress points to nothing (as an index of my_table), so the result is correcly nil.

On the other hand, when you compare vec2(1,1) == vec2(1,1) you do not compare the adress but the values of the 2 objects, because CODEA has 1/ defined a vec2 type and 2/ defined a ‘==’ method to compare them (this is not automatic, it has to be defined for each new userdata type, and it is done via metatbles, you will learn that later when you will get faliliar with LUA). So the result is logically true.

Hope that unveils a little bit the mystery… There is no ‘black magic’ in LUA, it is a really simple and reliable langage, just good ‘white magic’ because it is so good to program in LUA!

I don’t know if that’s “magic”. Operator overloading has been around long before Lua was invented. =)

Thank you all for all the insight into Lua. In case you can’t tell, I’m on day two with Codea and Lua, so my opinions above should be taken with large grains of salt. Salt licks, actually.

I am pretty clear on the error of my ways here. Clearer docs of the Codea vec2 type and its overloading of == would have been helpful. But this forum sure provided a super service for this Codea beginner. Thanks!

Agreed… I came here because there were things I didn’t understand about Codea and Lua, and I stayed because… well, because there are still things I don’t understand about Codea and Lua.

And the people are cool.

+1