Using 'Object' functions in Lua? - lua

I want to be able to have 'objects' with certain functions that refer to themselves (I have no idea what to call this) in Lua. I have seen code of what I'm trying to do but I have never understood what any of it actually means. I have tried looking over the Lua website but no luck.
Basic Code:
table = {}
function newTable(...)
...
return setmetatable(table)
end
function table:funcName(...)
...
end
Can someone explain what is going on here and how I can use this please? Thanks for reading!

missingno already mentioned one resource that explains how this works. You can also check out lua wiki's OOP section for more explanation and examples.
To summary briefly your example, starting with how to use it. Note, I changed some of the names so it doesn't affect the standard modules that comes with lua. You create a new object by calling newObject. You can invoke that object's methods using : followed by the method name:
-- create two instances
object1 = newObject()
object2 = newObject()
-- call 'my_function' method for object1
object1:my_function()
You'll need to know a bit about metatables to understand how this machinery works behind the scenes. When you perform a call like:
object1:my_function()
That is just syntax sugar for:
object1.my_function(object1)
This can be broken down further into:
object1["my_function"](object1)
Now object1 is just an empty table returned by newObject -- it doesn't have a "my_function" key. Normally this would result in an error because you're trying to call a nil value. However, you can change this behavior using metatables. The basic idea is to setup the __index metamethod to point to a table that holds your class methods:
object_table = {}
object_table.__index = object_table
function newObject(...)
return setmetatable({}, object_table)
end
The method lookup process will then look like this: object1 -> table. If object1 doesn't have a key, table is consulted next. If table has that key the associated value is returned. If table doesn't have it either then nil is returned since table doesn't have a metatable.
With this setup you can "override" a method for a particular object instance by just assigning the method name and function as key-value pair for that object.
object2.my_function = function (...)
-- do something different
end

Related

In Lua, access the evaluated value of a C function addressed via a userdata table

I have a piece of lua code that is called from a C program that passes it a table.
The table contains a table which has a field that LUA reports is of type "function".
I want to invoke that function and get its return value, but the following just causes a crash (????stack corruption????):
function myFunc (tableIn)
local interface = tableIn["interface"] -- type(interface) is table
local targetFunc = interface["targetFunc"] -- type(targetFunc) is function
local value = targetFunc()
...
end
I'm therefore assuming that I need to pass one or more parameters to targetFunc(...) but I have no idea what targetFunc() is expecting and I don't have access to the documentation or code for targetFunc - which I'm also guessing is written in C.
I've seen the thread lua - get the list of parameter names of a function, from outside the function and run the code as suggested - but that just seems to return "*temporary".
The question: is there some "standard" way of calling a C routine from LUA - or is there any other programmatic way (even a one-off) of finding out how many and what type of parameters targetFunc(...) needs.
Even an answer of "no - you need to see the code / doc for targetFunc(...)" would help!
Thanks in advance...

Lua functions: how to use tables as function arguments and self-document the code

When I have functions which take many arguments it's sometimes useful to pass a single table as an argument instead of many local variables.
function example_1(arg_one, arg_two, arg_three)
end
becomes
function example_2(arg_table)
arg_table.arg_one, arg_table.arg_two, arg_table.arg_three
end
The problem is, when calling the function somewhere else in code, it's hard to remember what arg_table needs to consist of. There are plenty of code-completion plugins for many editors which will help you with remembering the arguments for the example_1 function, but not for example_2.
Is there any way to write the example_2 function with a table parameter in a way that is still a table, but also shows the necessary parameters for the function inside the ()?
something like this (which does not work):
function example_2(arg_table = {arg_one, arg_two, arg_three})
end
Write your formal parameter list and documentation with separate parameters, as usual. Then document that if the first (and only) actual argument is a table, the effective arguments will be taken from the table using the formal parameter names as string keys.
You can keep the function parameters as they are and pass a table for convenience.
For example:
function example(arg_one, arg_two, arg_three)
-- do stuff
end
local tbl = {"value for arg_one", "value for arg_two", "value for arg_three"}
example(table.unpack(tbl))
Note that this doesnt work for tables with named keys.

How to pass variable by reference in Corona

I'm using Corona SDK.
I want to write a function which receives component as parameter and removes it like that:
function removeComponent(component)
if component then component:removeSelf() end
component = nil
end
Well, it works but my parameter does not get nil after using this function. Probably I have to pass it by reference, but I'm not sure it is possible with Corona.
This does not really make sense as presented in your example.
What exactly are you trying to accomplish? Is component a global ? Or a key in a table?
In your example, component is the name of a local variable in your function. Your component = nil only removes the value from the local variable, and thus will be lost.
If you want to have global effects, you'd need to pass the name of the variable you'd want to eliminate as string:
function removeComponent(component)
if _G[component] then -- exists globally?
_G[component]:removeSelf()
end
_G[component] = nil
end
Note that this style of programming (using the global table for this kind of things) is generally not a good idea. In the best case it can surprise you, in the worst case you end up zapping things like standard functions as print.
Therefore I'd recommend puttign things in their own table, and passing it on to the function.
Lua doesn't support passing by reference, but since it does support return values you can always achieve what you want using this idiomatic approach:
function removeComponent(component)
if component then component:removeSelf() end
return nil
end
And then call it like this:
a = removeComponent(a)
Edit: It's worth pointing out too that since Lua supports multiple return values and multiple assignments, you never actually need pass-by-reference. If you need several items updated, pass them in and return them and then do the call as
a,b = myFunction(a,b)
Its not different really than any other language. Passing by a value by reference (in C++ for example) would not stop any program from holding another copy of this same value elsewhere.
I know nothing of Corona, but this isn't really a Corona question so much as a Lua style question. However, if I had wrote it, I would ensure that the 'component' userdata or underlying value would clear itself up. If the userdata was accessed again, it should throw an error complaining about re-using a dead userdata.
I have written this code:
local component = display.newCircle(100, 100, 100);
local function removeComponent(c)
if component then component:removeSelf() end
component = nil
end
removeComponent(component)
if component == nil then print("Component is nil") else print("Component is not nil") end
And it prints "Component is nil". Perhaps you have a copy of your component somewere else or may be you forget to call function removeComponent or something else. Need to see more of your code

Use of metatables in Lua

I'm trying to implement a object notation in Lua scripts.
Here is what I succeeded to do with the C API:
I created a new global table "Test" as a class and added a field "new" in it, pointing to a function written in C
i.e I can do this in lua code: "local obj = Test.new()" (it calls the function "new")
The "new" C function creates and returns a new table, and registers functions in it as fields (e.g "add", "count"...)
i.e I can do this: "obj:add("mike")" and "obj:count()" (obj is passed as first arguments with the ":" notation)
2 questions:
1) Everything works as expected, but the thing I'm wondering is: What is the advantage of using metatables in my case?
I see everywhere that metatables can help me to achieve what I tried to do, but I don't understand where they would be useful?
Adding fields to tables as methods isn't correct?
How could metatables help me (If added as my tables metatables)?
2) In fact I'm trying to reproduce the behaviour of C++ in Lua here.
For example, when I write this in C++: "Test *obj = new Test();"
I expect C++ and the constructor of Test to return me a pointer of an instance of Test.
This is exactly what I'm trying Lua to do for me.
The thing is that I use a table in this case, as the return of "new", but not a pointer so I can call methods on it later with Lua (using its fields), like a standard C++ object (with the operator ->).
To be able to retreive the actual pointer of my class in the C fonctions, I added a field "ptr" (light uservalue) to the table returned by "new". Without it, I would have been able to manipulate only the Lua table in my C function, nothing more (so no more method calls on the real pointer).
My second question is, Is it the right way to do it?
Do you have better idea on how to be able to manipulate my pointer everywhere without this "ptr" field?
Thank you,
Nicolas.
The main reason is that you get the __index metamethod.
Without it, every instance of a object has to have all the functions associated with it: which can make tables why large; and use a lot of memory.
local methods = {
foo = function() return "foo" end ;
bar = function() return "bar" end ;
bob = function() return "bob" end ;
hen = function() return "hen" end ;
}
So you have either
function new_no_mt ( )
local t = {}
for k , v in pairs ( methods ) do t [ k ] = v end
return t
end
vs
local mt = { __index = methods ; }
function new_mt ( )
return setmetatable ( { } , mt )
end
There are other benefits too;
defining operators;
easy type comparison via comparing metatables.
Changing method in metatable changes it for all objects, but changing it on one object only changes it for that object.
Otherwise, what you are trying to do sounds like the perfect situation for userdata.
userdata can only be indexed when you have an __index metatmethod (theres no table to put methods in)
What is the advantage of using metatables in my case?
Here's one.
Test.new = function() end
I just destroyed your ability to create new Test objects globally. If you had protected Test with a metatable, I would have had to really work to be able to do that.
Here's another:
local myTest = Test()
You can't do that without a metatable (overload the __call metamethod). And it looks much more natural for Lua syntax than calling Test.new.
And another:
local testAdd = Test() + Test()
Operator overloading. You can't do that without metatables.
Also:
This is exactly what I'm trying Lua to do for me.
Here's a tip: don't.
Different languages are different for a reason. You should do things in Lua the Lua way, not the C++ way. I can understand wanting to provide certain C++ mechanisms (like overloading and so forth), but you shouldn't use new just because that's what C++ uses.
Also, there are plenty of libraries that do this work for you. SWIG and Luabind are two big ones.

Lua MiddleClass. How to pass "self" from another file

Say, If i have two or more files using the middleclass extension more or less like this. I omitted some of the obvious middleclass implementation code.
File A:
function Battlefield:initialize()
self.varA
self.varB
end
function Battlefield:attack()
--I want to use self.varA here
end
File B
BattlefieldInstance = Battlefield:new()
function doStuff()
BattlefieldInstance:attack()
end
I know this structure more or less works because i already use it plenty on my project, but my problem is that i want to use these self variables. Normally a self instance is passed between functions inside the same file to do this, but when i do it from another file i obviously can't pass self, because it would be another self, and i need the self from the file where the function is located. Sorry if my question is a bit confusing. I'll try and clarify any questions there are.
I have no idea what middleclass is, but I think you're confusing yourself. The way self works in Lua is a function that looks like function Battlefield:attack() is absolutely the same thing as function Battlefield.attack(self). In other words, self is just an implicit first parameter to the function. And a method call instance:attack() is exactly equivalent to instance.attack(instance) (though it won't evaluate instance twice if you use an expression there).
In other words, BattlefieldInstance:attack() should do exactly what you want.
'self' is a keyword that means 'the current object'. So in the case of Battlefield functions, 'self.varA' inside the function is the same variable as 'Battlefield.varA' outside the function.
Middle Class was a lib that I first saw developed for Love2D; I assuming its the same one that corona is using? (I've used Corona a fair bit... but not Middle Class's OOP system)
either way you can also try using meta tables directly, as so:
---FILE A---
Battlefield= {}
Battlefield.__index = Battlefield
function Battlefield:new()
return setmetatable({var1 = 'somedata', var2 = 'somemodata', var3 = 'lotsodata'}, Battlefield)
end
function Battlefield:attack()
print(self.var1)
end
---FILE B---
BattlefieldInstance = Battlefield:new( )
function doStuff()
BattlefieldInstance:attack()
end
and that'll print out self.var1 (somedata).
Hope this helps!

Resources