Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Comparison Error with userdata types

I am using “for k, v in pairs()” to go through a table to see if a value is present. In this case, for example, I am looking for a vec2 object (i.e. “if v == someVector” ). Everything is fine, I can do an equality comparison “==“ against any other value in the table—vec2s, strings, numbers, tables, functions—until I put another userdata type in the table, say a color.
Then I something like this error: “[string "print( aColor == aVector )"]:1: bad argument #2 to '__eq' (color)”
If I put them in the other order, I get a similar error “[string "print( aVector == aColor )"]:1: bad argument #-1 to '__eq' (vec2)”

Is this expected? Is there a way around this, or should I just make sure that I don’t have different userdata types in the same table?

Thanks!

Comments

  • JohnJohn Admin Mod
    Posts: 572

    @AlbertEinlime you could do check if they both have the same metatable first then check for equality

    if getmetatable(value1) == getmetatable(value2) and value1 == value2 then
    ...
    end
    

    This way only things that are the same type (in terms of userdata) will be compared.

  • dave1707dave1707 Mod
    Posts: 7,533

    I assume you’re using type to determine what’s in the table. Can you show a little demo of what you’re doing.

  • dave1707dave1707 Mod
    Posts: 7,533

    Thought I’d create an example based on @John post just to see how it would work.

    function setup()
        tab={}
        tab[1]=1234
        tab[2]="1234"
        tab[3]={1,2,3,4}
        tab[4]=xx
        tab[5]=color(255,0,255)
        tab[6]=vec2(12,34)
        tab[7]=vec3(56,78,55)
        tab[8]=vec4(56,78,55,12)
    
        c=getmetatable(color())
        v2=getmetatable(vec2())
        v3=getmetatable(vec3())
        v4=getmetatable(vec4())
    
        for a,b in pairs(tab) do
            print(a,type(b))
            t=getmetatable(b)
            if t==c then
                print("equal to color")
            end
            if t==v2 then
                print("equal to vec2")
            end
            if t==v3 then
                print("equal to vec3")
            end
            if t==v4 then
                print("equal to vec4")
            end
        end   
    end
    
    function xx()    
    end
    
  • Thank you @John, @dave1707,

    That’s what I was looking for.

    I was using this while testing some modifications to CodeaUnit, and that will do just fine.

    So is this expected behavior? In a dynamically typed language, I feel that if aString == aTable can return false without throwing an error, so should userdataTypeA == userdataTypeB. Would this count as a bug?

    On an unrelated note, I have found an action or two that reliably cause Codea to crash. Is it better to write that up in the Bugs forum or to use the BitBucket issue tracker?

    Again, thank you both for showing me what to use and how to use it.

  • edited January 25 Posts: 429

    Just to throw in another example, here's my is_a function which tests for equality of type, taken from the VecExt library on github:

    --[[
    The function "is_a" extends the capabilities of the method "is_a" which is automatically defined by Codea for classes.
    
    Parameters:
    a: object to be tested
    b: test
    
    The tests work as follows.
    
    1. If the type of b is a string, it is taken as the name of a type to test a against.
    2. If the type of b is a table, it is assumed to be a class to test if a is an instance thereof.
    3. If the type of b is a userdata, the test is to see if a is the same type of object.
    4. If b is a function, then it is replaced by the value of that function.
    --]]
    
    function is_a(a,b)
        if type(b) == "function" then
            b = b()
        end
        if type(b) == "table" and b.___type then
            b = b()
        end
        if type(b) == "string" then
            return type(a) == b
        end
        if type(b) == "table"
        and type(a) == "table"
        and a.is_a
        then
            return a:is_a(b)
        end
        if type(b) == "userdata"
        and type(a) == "userdata"
        then
            if a.___type or b.___type then
                return a.___type == b.___type
            end
            return  getmetatable(a) == getmetatable(b)
        end
        return false
    end
    
Sign In or Register to comment.