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.
Related
I have a personal project and a pure lua writed object module which provides metatable with methods filter map etc to a table , I don't want to require and setmetatable for every line local foo={}
Global Constructor
I have a personal project and a pure lua writed object module which provides metatable with methods filter, map etc to a table , I don't want to require and setmetatable for every line local foo={}.
You can avoid the need for require by just ensuring that your "object module" is always loaded first, setting global variables. I consider require to be cleaner however as it makes clear the dependencies of your files (and does not pollute the global environment).
To avoid the need for setmetatable, you can write yourself a constructor function:
local metatable = ...
function Table(t) -- NOTE: global function
return setmetatable(t, metatable)
end
then, in another file which you ensure only runs after this file was executed:
local foo = Table{}
You might want to shorten Table to T if you use this very often.
Setting a metatable for all (new) tables
Do you really want this?
First of all: You probably do not want local t = {} to set a metatable on t. This would mess with linters like Luacheck while also making your code hard to follow for everyone familiar with Lua but unfamiliar with this hack.
Setting a metatable with __index also interferes with the usage of tables as dictionaries / hash maps; users now need to use rawget / rawset to circumvent your metatable. Consider the following snippet:
local dict = { filter = "bar" }
print(dict.filter) -- "bar", as expected
print(dict.map) -- filter function - unexpected
print(rawget(dict, "map")) -- nil, as expected
It will also harm performance of every table access. Do you really want this just for some syntactic sugar?
Furthermore, if you heavily set metamethods (such as the arithmetic metamethods) even if it doesn't really make sense, you again get unexpected behavior by allowing passing tables where numbers are expected etc. Lua's partial strictness when dealing with incompatible types is what distinguishes it from JS.
How to do it
how to automatically set default metatable to every newly created table?
This is not possible in general; the proper way to set metatables is to explicitly use constructors.
debug.setmetatable, primitives & functions
Using debug.setmetatable, you can set "shared"/"common" metatables for all primitive types (boolean, number, string) as well as functions. You can not set a shared metatable for objects this way however.
Hooking global/environmental variable access
This is what koyaanisqatsi's snippet does: It catches global variable access and sets the metatable on all new table global variables. This is insufficient as it forces you to use global/environmental variables, which is both bad for performance and code quality. It will in particular not work at all for local variables such as the local foo = {} in your example. It will also not work for temporary variables in expressions (consider ({...}):filter(...)).
Debug Hooks
The following approach would be more reliable than hooking environmental variable access:
Set a debug hook that runs after every instruction.
Iterate over locals & upvalues and set the metatable for each table; perhaps remember old/new locals/upvalues/tables.
Eventually consider doing this recursively, for structures such as {{}}.
Obviously this would be awfully slow. It is very likely that there still exist many "edge cases" this doesn't catch (what about table creation in C, for instance?).
Forking Lua
The only proper solution would be to add such a feature - a default metatable for all tables - to the language by forking it and implementing this right in the function where Lua creates new tables. This is the only way this could be implemented adequately - that is, with adequate performance & reliability.
For this you can set/use the Metamethod __newindex that triggers at defining something New.
For "every newly table" the right Place is: _G
_G = setmetatable(_G,
{__index = table,
__newindex = function(tab, key, value)
print('[__newindex]:', tab, key, value)
if type(value) == 'table' then
rawset(tab, key, setmetatable(value, getmetatable(tab)))
else
rawset(tab, key, value)
end
return
end
})
--[[ Example of use:
> a = {}
table: 0xf7ed2380 a table: 0xf7ed9738
> a:insert('Hi There!')
> print(a:concat())
Hi There!
> a[#a + 1] = {}
[__newindex]: table: 0xf7ed9738 2 table: 0xf7edbe40
]]
What will not work under LuaJIT (Lua 5.1)?
__gc will not be triggered at all
table.insert({'I (Key [1]) am a string in a table'}) will not triggered by __newindex
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
So if I have this lua function
function dostuff(x)
function foo () x=x+1; end
foo();
return x;
end
And it turns out i need foo many times. But it is mainly useful because it has access to the x upvalue. Is there a way to pull foo out of dostuff, but still have it access to x?
I tried to put foo() global and adding it to dostuff, like this:
function foo () x=x+1; end
function dostuff(x)
foo();
return x;
end
dostuff.foo = foo
Which does not work as in lua functions are distinct from tables (unlike js).
I still have a feeling that this does work in lua, probably using metatables. But I just not know enough about it yet. I know a lot of ways to avoid this and work around it. I am just curious if there is a way to do it.
Maybe another way to look at is, can you call a global function with a choice of closure?
A cleaner and clearer way would be to just pass arguments to foo, which I would recommend.
Another would be to use global variables, or variables local to some chunk (i.e. module or block), common to all related functions.
Otherwise, I didn't find any way to do this. I would suggest redesigning your approach.
What you want is dynamic scoping. Unfortunately Lua doesn't have dynamic scoping. It has lexical scoping. In JavaScript you may simulate dynamic scoping using eval, but Lua doesn't have eval.
As a last resort you could use inheritance. The way I usually do inheritance in Lua is using an extend function, which is similar to the Object.create function in JavaScript:
local o = {}
function o:extend(table)
return setmetatable(table, {
__index = self
})
end
Using this method I can now create an object which will be used for dynamic scoping:
local dynamic = o:extend {}
function dynamic:foo()
self.x = self.x + 1
end
The method foo is dynamic in the sense that it's variable x doesn't point to any specific value. It depends on the value of self which can be changed. We use it as follows:
function dostuff(x)
local scope = dynamic:extend {
x = x
}
scope:foo()
return scope.x
end
However instead of creating a new scope every time you execute dostuff it would be better to simply do:
local myscope = dynamic:extend {}
function myscope:dostuff(x)
self.x = x
self:foo()
return self.x
end
In fact if you decide to refactor your code as shown above then you don't even need inheritance. All you need to do is:
local myscope = {}
function myscope:foo()
self.x = self.x + 1
end
function myscope:dostuff(x)
self.x = x
self:foo()
return self.x
end
The only difference is that now you would have to call myscope:dostuff instead of calling dostuff directly. This is however a good thing as you don't pollute the global scope.
This is the way I would do it, and this is the way I would recommend that you do it as well. All the Lua standard library functions are also defined on objects.
Since you gave only a crude example of what you wanted to do and not your actual use case, suggesting an alternative is a bit hard. To start off, to me this is what it sounds like you want
local x;
function foo() x=x+1 end
function dostuff(a)
x = a;
foo();
return x;
end
My problem here is that foo is so simple and there is absolutely no reason to not make it a function that takes a value x and returns x+1. Further, while the necessary initialisation step for x is not really bad and should not result in any bugs right away, it will make development a bit odd when you have to remember to initialize variables for another function and may create a debugging hell if you don't.
So, since Lua also supports multiple return values, the code above is actually a bad idea that gives you no benefit over something like:
function foo(a,b,c) return a,b,c end
function dostuff()
a,b,c = foo(a,b,c);
end
Since you wrote about code re-use, here is a general ... nudge to what else you can do, which is making use of closures.
You can turn your structure around and make not foo take x as an argument, but have dostuff take foo as an argument:
function dostuff(foo)
return foo()
end
dostuff(function() return 1 end)
dostuff(function() return 2 end)
Taking this a step further brings you to a technique called partial application.
function dostuff(foo)
return function(x)
return foo(x);
end
end
dostuff(function(x) return x+1 end)(17)
local f = dostuff(function(x) return x+1 end)
f(17)f(18)f(19) -- ...
Now that means you can not only modify the way your function works inside from the outside, but you can save that state too. As an added bonus you can also put expensive operations, that you only have to do once per "instance", in the outer function and save some performance.
I hope these are enough ideas to help you with your code re-use issues ;)
I am trying to understand what this function does. Can anyone explain this to me?
function newInstance (class)
local o = {}
setmetatable (o, class)
class.__index = class
return o
end
It is called like this:
self = newInstance (self)
This function apparently serves to provide a variant of OOP in Lua (a bit sloppy in my opinion).
This is a factory for a class.
It may be rewritten as follows, for clarity:
C = { }
C.foo = function(self) -- just some method, so class would not be empty
print("foo method called", tostring(self))
end
C.__index = C -- (A)
function newInstance(class)
return setmetatable({ }, class) -- (B)
end
Now if we create two new instances of C, we clearly see that both have a method foo(), but different self:
o1 = newInstance(C)
o1:foo() --> foo method called table: 0x7fb3ea408ce0
o2 = newInstance(C)
o2:foo() --> foo method called table: 0x7fb3ea4072f0
The foo methods are the same:
print(o1.foo, o2.foo, o1.foo == o2.foo and "equal" or "different")
--> function: 0x7fb3ea410760 function: 0x7fb3ea410760 equal
This is because table C (the "class") is an __index ((A) above) of metatable of o1 and o2, set in (B). But o1 and o2 are actually two different tables, created at (B) (the "class instances" or "objects").
Note: we set C.__index to be equal to C itself at (A) so we would reuse one table. Following has the same effect:
prototype = { }
prototype.foo = function(self) -- just some method, so class would not be empty
print("foo method called", tostring(self))
end
C = { __index = prototype }
function newInstance(class)
return setmetatable({ }, class)
end
o = newInstance(C)
This is used to achieve object-oriented behavior in Lua. Lua uses prototype-based inheritance (similar to Javascript) instead of class-based inheritance (like Java or C++).
The idea is that all class methods are implemented as part of a prototype object and inheriting objects delegate to the prototype upon call.
For example, assume you want a class myClass providing a method getMagicNumber:
local myClass = {
getMagicNumber = function(self)
return self.theNumber;
end };
local obj = newInstance(myClass);
obj.theNumber = 42;
print(obj:getMagicNumber()); -- supposed to return 42
It's kind of a trivial example, but I hope you get the idea. What happens is this: newInstance creates a new table with its metatable pointing to myClass and also ensuring that the __index field of the metatable points to myClass as well.
As the Lua manual on __index describes, when you now attempt to call getMagicNumber on that new table, the following happens: First Lua attempts to find the field getMagicNumber in the obj table. Since that table is empty though, it now searches its __index table (myClass) for that field. Since the field is found there, it now calls the function found in myClass.
Programming in Lua discusses this mechanism in great detail if you need to know more.
You're not alone it took me a fair bit of time to grok this code. Here's my interpretation
each table can have a netatable, the metatable can store amongst other things functions indexed by name, and setmetatable sets the value of the metatable naturally enough.
The line class._index = .. is where the magic happens.
When you try to call a function using self.fn1(), Then lua looks up in the self a name fn1. If it can't find it then it looks in self's metatable for a table __index, and looks for a 'fn1' in the table stored there.
Now the metatable for self in your example is class, so lua looks for an __index entry in the metatable (class) to see if there's a function named fn1 in that table, and there is, so it's returned. You need to set the __index for class back to itself so that lua will look in the same metatable - confusing hey.
(as an aside the assignment to __index only needs to happen once, but for some reason it's always done in the new operator in all the lua examples - I take it outside of the new in my classes - saves a few cycles)
You then return the new table o, lua is garbage collected so returning a local creates a new table each time.
function newInstance (class)
local o = {}
setmetatable (o, class)
class.__index = class
return o
end
hth
What is the difference between the following Lua scripts in terms of function scope. How would it effect the need to require 'calculator' in some other Lua script. And how would it be referenced in say a LuaState.getGlobal(function_name). What would be its proper function name? Also any comment on advantages/disadvantages of the declaration approaches.
A) Calculator.lua
function foo(n)
return n+1;
end
B) Calculator.lua
calc= {}
function calc.foo(n)
return n+1;
end
C) Calculator.lua
function foo(n)
return n+1;
end
function calculator()
calc = {}
calc.foo=foo
return calc
end
I don't know what it is you mean exactly by the "scope" of these scripts. Exactly what these scripts do depends on how they're being executed. You could give them a different environment, thus changing what they think of as "globals".
So, I will explain what each of these scripts does based on the assumption that you are loading them with dofile, dostring, or something of the like. That is, you're applying them to the global environment.
A)
This creates a single global variable, foo, which is a function.
B)
This creates a single global variable, calc, which is a table. This table has a single entry, with the key foo, who's value is a function.
C)
This creates two global variables. foo is a function. calculator is also a function. Each call to calculator will cause the global variable calc to be overwritten. The new value of calc will be a table that has a single entry, with the key foo, who's value is a copy of what is stored in the global variable foo.
It's hard to say what the "advantages" of method C are, since it makes no sense. It creates two functions instead of one, and that second function keeps creating new tables.
B is just a "namespace" scoped version of A. The general expectation with Lua modules is that including them will usually create some table that will contain all of the functions in that module, to avoid name conflicts with existing global state. In that regard, B may be better. But it depends mostly on what this script will be used for.
Personally, for simple shell scripts and utility scripts, I don't bother with proper module scoping. When I do make a proper module, I generally use the module Lua function.
Not exactly an answer, but a comment on semantics - in Lua, you do not declare a function, you create it. The function becomes available at the time the function(...) ... end is executed. How it is available depends on where you store it.
You have to remember that:
function myfun(foo) print('foo') end
is just syntactic sugar for:
myfun = function(foo) print('foo') end
If you do not do anything special, myfun becomes a global variable stored in the global state (accessible through _G). If you say local myfun before actually calling function myfun() end, the function (actually a closure) will be stored in the local variable and available only to the scope of the local variable.
If you use require, it just finds the file and loads it once. It doesn't do anything fancy with the module like hiding globals, etc. So if you write function foo() end in your module Calculator.lua, then calling require 'Calculator' will create a function in global foo, which you can access using LuaState.getGlobal("foo"). If you create a table of functions (step B), you have to use 2 steps:
L.getGlobal("calc") -- pushes the "calc" global (a table) to the stack
L.getField(-1, "foo") -- gets the "foo" field from the table