Custom types in Lua

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Lugen
Prole
Posts: 24
Joined: Mon Nov 10, 2014 8:36 am
Location: Sweden

Custom types in Lua

Post by Lugen »

Pardon if this has already been discussed somewhere else. Searched the forum but could not seem to find anything.

Lets say I've defined a table for a certain "class" with metamethods and I want this "class" to have its own type definition so that if I used as argument for the type() function it would return something else other than "table".
Is this possible to do this just in lua or do you know of any nice workaround to achieve something similar?

As a bonus, I recently found out about the FFI library in LuaJIT which allows you to define c-data-structures and function bindings directly in lua-code. You can define new types (checked by a different function though) here but after some testing I don't think I would be able to convert all the classes I would like to due to some of their fields are tables.
http://luajit.org/ext_ffi.html
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Custom types in Lua

Post by airstruck »

I think someone suggested a __type metamethod once on the lists but it didn't gain any traction. For any "class" where you want to check if some object is an "instance" of it, you could just put a property in the prototype like isWhatever = true. If you're doing this kind of typechecking so much that that would be inconvenient, you're probably not using the language in an idiomatic way.

I suppose you could also write a function taking an "instance" and a "class," and walk up the prototype chain until you either hit the "class" you were looking for or the end of the chain.
szensk
Party member
Posts: 155
Joined: Sat Jan 19, 2013 3:57 am

Re: Custom types in Lua

Post by szensk »

You could have a __type metamethod and then override the default type() function to call the metamethod if it has it, or otherwise call the old type function if it doesn't.
Last edited by szensk on Mon Jun 15, 2015 9:50 pm, edited 1 time in total.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Custom types in Lua

Post by airstruck »

szensk wrote:You could have a __type metamethod and then override the default type() function to call the metamethod if it has it, or other was call the old type function if it doesn't.
Shadowing type sounds like asking for trouble, it's going to take anyone else looking at the code a few minutes to figure out what you've done. Might as well make a new function for it. But why use a meta-property when you can just stick a property in the prototype and check that? Nobody's likely to complain if your Dude class has a property like isDude = true; no reason to go digging around in a metatable for it.
User avatar
Lugen
Prole
Posts: 24
Joined: Mon Nov 10, 2014 8:36 am
Location: Sweden

Re: Custom types in Lua

Post by Lugen »

time thief wrote:I think someone suggested a __type metamethod once on the lists but it didn't gain any traction. For any "class" where you want to check if some object is an "instance" of it, you could just put a property in the prototype like isWhatever = true. If you're doing this kind of typechecking so much that that would be inconvenient, you're probably not using the language in an idiomatic way.

I suppose you could also write a function taking an "instance" and a "class," and walk up the prototype chain until you either hit the "class" you were looking for or the end of the chain.
A __type metamethod sounds like it could be pretty useful indeed. Fortunately I only need this for a rather specific case right now so checking by property will probably suffice.

Could you elaborate on your second suggestion? Would it be something like:

Code: Select all

function checkType(instanceTable , originalClassTable)
-- Compare fields, return true or false
end
szensk wrote:You could have a __type metamethod and then override the default type() function to call the metamethod if it has it, or other was call the old type function if it doesn't.
That is a valid option too. I suppose "__type" could be named anything as it doesn't exist in the lua-api.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Custom types in Lua

Post by airstruck »

Lugen wrote:A __type metamethod sounds like it could be pretty useful indeed.
I think it might do more harm than good. It's nice knowing that type will return one of a small set of possible values. If you want to know whether something is a function or table, but instead type is returning something like "monster," it's going to be an excercise in frustration... which is another good reason not to shadow type as suggested in another reply (if shadowing built-in stuff doesn't raise enough red flags on its own).
Lugen wrote:Fortunately I only need this for a rather specific case right now so checking by property will probably suffice.
Yeah, keep it simple.
Lugen wrote:Could you elaborate on your second suggestion?
I could, but I'd rather not... I don't think it's a great solution; it sort of encourages long inheritance chains. But basically you would just get the metatable for instanceTable, and get its __index property, and that's your new instanceTable, and keep doing that until instanceTable is equal to either originalClassTable or nil. Of course that makes some assumptions about how you've handled classes/inheritance, but it should work for most cases.
User avatar
ejmr
Party member
Posts: 302
Joined: Fri Jun 01, 2012 7:45 am
Location: South Carolina, U.S.A.
Contact:

Re: Custom types in Lua

Post by ejmr »

Personally if I know that (for example) a function parameter is going to be a class in the form of a table then I will check its type, if necessary, by looking at its metatable, e.g.:

Code: Select all

if getmetatable(object) == WhateverClass.Metatable then ... end
If you use a third-party library for OOP then it may already provide something to that effect, although I got the impression from your post that you're not using anything like that.
ejmr :: Programming and Game-Dev Blog, GitHub
南無妙法蓮華經
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Custom types in Lua

Post by kikito »

Let me start by saying that when doing OOP, "asking something what's his type" is considered a "bad smell in the code". There are some cases where it is reasonable to do so, but in general what you do is implementing methods in that class/type.

This is how you would do a "type switch" with middleclass, using instanceOf:

Code: Select all

function printClass(obj)
  if obj:instanceOf(A) then
    print('Class A')
  else if obj:instanceOf(B) then
    print('Class B')
  end
end
And this is how you would use that function in an object:

Code: Select all

printClass(x)

But in object oriented programming what's recommended do is creating a method in A and B:

Code: Select all

function A:printClass()
  print('Class A')
end
...
function B:printClass()
  print('Class B')
end
Then you can just do this:

Code: Select all

x:printClass()
The "if-else-if-else" is done "automatically" for you. There is another advantage: Imagine that you do the "function with ifs" thing more than once or twice. And then imagine that you add a new class called C. Then you will have to "hunt" all places where you made a "class switch" and manually change them. Using the second option, you just need to create C, implement the class-specific methods on it (like printClass) and the code that worked for A and B will also work for C. No "hunting" needed.
When I write def I mean function.
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Custom types in Lua

Post by Xgoff »

kikito wrote:Let me start by saying that when doing OOP, "asking something what's his type" is considered a "bad smell in the code". There are some cases where it is reasonable to do so, but in general what you do is implementing methods in that class/type.

This is how you would do a "type switch" with middleclass, using instanceOf:

Code: Select all

function printClass(obj)
  if obj:instanceOf(A) then
    print('Class A')
  else if obj:instanceOf(B) then
    print('Class B')
  end
end
And this is how you would use that function in an object:

Code: Select all

printClass(x)

But in object oriented programming what's recommended do is creating a method in A and B:

Code: Select all

function A:printClass()
  print('Class A')
end
...
function B:printClass()
  print('Class B')
end
Then you can just do this:

Code: Select all

x:printClass()
The "if-else-if-else" is done "automatically" for you. There is another advantage: Imagine that you do the "function with ifs" thing more than once or twice. And then imagine that you add a new class called C. Then you will have to "hunt" all places where you made a "class switch" and manually change them. Using the second option, you just need to create C, implement the class-specific methods on it (like printClass) and the code that worked for A and B will also work for C. No "hunting" needed.
tl;dr: duck typing
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Custom types in Lua

Post by airstruck »

Xgoff wrote:tl;dr: duck typing
Could you explain what you mean by that? To me that post seems to be about favoring subtype polymorphism over typechecking; I'm not seeing the connection to duck typing.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 13 guests