local tbl = {a = 1}
-- Passed and executed function
function tbl:handleFunc(x, y)
print(self.a + x + y)
end
-- I know the above code is syntax sugar.
-- tbl["handleFunc"] = function(self, x, y)
-- print(self.a + x + y)
-- end
-- Register event handlers that I can't control the call
Frame:SetScript("OnClick", tbl.handleFunc)
-- Probably called when an event occurs.
tbl.handleFunc(2, 3)
-- Then it will be like this.
tbl.handleFunc(2, 3, nil)
-- So I wrote a function like this
function tbl.handleFunc(x, y)
local self = tbl -- This variable is too cumbersome
-- And this way, every time I call a function, I need to check whether the function definition is a dot (.) Or colon (:)
end
When calling a function, In situations where you can't pass self, Is there a way to use self?
If not, how should I design?
[Solved] I used a translator but I want to be polite. Thank you for the nice answers.
One way to avoid unnecessary work is to write a function that will wrap the function for you before you register it as a handler:
local tbl = {a = 1}
function tbl:handleFunc(x, y)
print(self.a + x + y)
end
function wrap_with(obj, func)
return function(...)
return func(obj, ...)
end
end
Frame:SetScript("OnClick", wrap_with(tbl, tbl.handleFunc))
Just use an anonymous function that calls the actual function
Frame:SetScript("OnClick", function(x,y) tbl:handleFunc(x, y) end)
How to define functions into lua's table? I try this code but doesn't work.
I want to use table:myfunc().
local myfunc
myfunc = function(t)
local sum = 0
for _, n in ipairs(t) do
sum = sum + n
end
return sum
end
mytable = {
1,2,3,4,5,6,7,8,9
}
print(myfunc(mytable)) -- 45
I think myfunc has not problem.
table.myfunc = myfunc
print(mytable:myfunc())
-- lua: main.lua:18: attempt to call method 'myfunc' (a nil value)
-- stack traceback:
-- main.lua:18: in main chunk
-- [C]: ?
print(mytable) shows table: 0x9874b0, but it is not defined function to the table?
mytable.myfunc = myfunc
print(mytable:myfunc()) -- 45
This worked. Is it the only prefer way to do this?
there are plenty of ways to define a function within a table.
I think the problem with your first code is that you have this:
table.myfunc = myfunc
where it should be:
mytable.myfunc = myfunc
In your case mytable.myfunc is nil as you never assigned a value to it
You could just write
local mytable = {}
function mytable.myfunction()end
or
mytable.myfunction = function()end
or
mytable["myfunction"] = function()end
or define myfunc separately and assign it to mytable.myfunc later like you did
If you want to access other table members from your function I recommend defining the function like that:
function mytable:myfunc()end
which is syntactic sugar for
function mytable.myfunc(self)end
If you do so you can access mytable's member trough the keyword self
In your case it would end up like:
function mytable:myfunc()
local sum = 0
for _, n in ipairs(self) do
sum = sum + n
end
return sum
end
So you don't need the function parameter t anymore and you can run the desired mytable:myfunc()
Otherwise you would have to write mytable:myfunc(mytable).
table.myfunc = myfunc
print(mytable:myfunc())
This cannot work, because mytable has no member called myfunc, table does.
you would either have to write
table.myfunc = myfunc -- assign myfunc to TABLE (not the same as mytable)
print(table.myfunc(mytable)) -- as with most other functions in table
or
mytable.myfunc = myfunc -- assign myfunc to MYTABLE
print(mytable:myfunc()) -- syntactic sugar for print(mytable.myfunc(mytable))
also, you can just define the function as either
function mytable:myfunc() -- syntactic sugar for mytable.myfunc(self)
-- do something
-- use "self" to access the actual table
end
or
function table.myfunc(t)
-- do something
end
Is there any difference between
local splitPathFileExtension = function (res)
end
and
function splitPathFileExtension(res)
end
? I understand in the first case this function is anonymous but this is the only difference?
They are almost exactly the same thing (other than the fact that you've specified the first function as local and not the second one.)
See the manual on function definitions:
The statement
function f () body end
corresponds to
f = function () body end
The statement
function t.a.b.c.f () body end
translates to
t.a.b.c.f = function () body end
The statement
local function f () body end
translates to
local f; f = function () body end
not to
local f = function () body end
(This only makes a difference when the body of the function contains references to f.)
All functions are anonymous, they don't have names. A function definition is in fact an assignment statement that creates a value of type function and assigns it to a variable.
The second code is syntactic sugar that's equivalent to:
splitPathFileExtension = function (res) end
So, other than the first is local while the second is global, there's no difference between the two ways of function definition.
so i have a lua file analogous to this:
x = { __index = x}
constructor = function()
local o = {}
return setmetatable(o,x)
end
function x:print()
print("hello world")
end
i type the following into the interpretr:
dofile "file.lua"
a = constructor()
a:print() --error attempt to call method 'print' (a nil value)
dofile "file.lua"
a = constructor()
a:print() -- hello world
the method works the second time i import the file but not the first. why is this?
I have tried changing the order (putting the constructor function last) and it was the same.
The first time x is nil. It gets defined and then used the second time.
You need to write x = {}; x.__index = x.
I'm wokring with Lua 5.2, and for the sake of this question, assume that the tables are used exclusively as arrays.
Here's a function that returns the tail of an array (the array minus its first element):
function tail(t)
if # t <= 1 then
return nil
end
local newtable = {}
for i, v in ipairs(t) do
if i > 1 then
table.insert(newtable, v)
end
end
return newtable
end
For instance:
prompt> table.concat(tail({10, 23, 8}), ", ")
23, 8
However this is achieved by returning a new copy of the table. Is there a way to avoid the creation of a new table?
I am looking for the equivalent of C's returning a pointer to the next element (t++). Is it possible?
As already explained, this is normally impossible.
However, using metatables, you could implement a tail function that performs what you want without copying all the data, by referencing the original table. The following works for most operations in Lua 5.2, but for example not for table.concat:
function tail(t)
return setmetatable({}, {
__index = function(_, k) return t[k+1] end,
__newindex = function(_, k, v) t[k+1] = v end,
__len = function(_) return #t-1 end,
__ipairs = function(_) return
function(_, i)
if i+1==#t then return nil end
return i+1, t[i+2] end,
t, 0 end,
__pairs = function(t) return ipairs(t) end,
})
end
This is the nicest way I know to implement tail(). It makes one new table, but I don't think that's avoidable.
function tail(list)
return { select(2, unpack(list)) }
end
Nicol is correct that you can't reference a slice of an array, but there is an easier/shorter way to do what you want to do:
function tail(t)
local function helper(head, ...) return #{...} > 0 and {...} or nil end
return helper((table.unpack or unpack)(t))
end
print(table.concat(tail({10, 23, 8}), ", ")) will then print 23,8.
(added table.unpack or unpack to make it also work with Lua 5.2)
I am looking for the equivalent of C's returning a pointer to the next element (t++). Is it possible?
No. The only possible reason you could want this is performance. Such a feature is only found in low-level programming languages. Lua is a scripting language: performance is not such a priority that this would be implemented.
Just make another table like you're doing, or use table.remove to modify the original. Whichever works best for you. Remember: the big, important objects like tables and userdata are all stored by reference in Lua, not by value.
prapin's suggestion, to use metatables to present a view of the sequence, is roughly the way I'd do it. An abstraction that might help is defining a metatable for segments, which can be an 0-ary function that returns a pair of a table and an offset index - we are only using functions here to represent tuples. We can then define a metatable that makes this function behave like a table:
do
local tail_mt = {
__index = function(f, k) local t, i=f(); return t[k+i] end,
__newindex = function(f, k, v) local t,i=f(); t[k+1] = v end,
__len = function(f) local t,i=f(); return #t-i end,
__ipairs = function(f)
local t,i = f ()
return
function (_, j)
if i+j>=#t then
return nil
else
return j+1, t[i+j+1]
end
end, nil, 0
end,
}
tail_mt.__pairs = tail_mt.__ipairs -- prapin collapsed this functionality, so I do too
function tail (t)
if type(t) == "table" then
return setmetatable ( function () return t, 1 end, tail_mt )
elseif type(t) == "function" then
local t1, i = t ()
return setmetatable ( function () return t1, i+1 end, tail_mt )
end
end
end
With __index and __newindex metamethods, you can write code such as f[2]=f[1]+1.
Although this (untested) code doesn't endlessly create one-off metatables, it is probably less efficient than prapin's, since it will be calling thunks (0-ary functions) to get at their contents. But if you might be interested in extending the functionality, say by having more general views on the sequence, I think this is a bit more flexible.