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
Related
I initially came across this while developing my game in LOVE2D, and I can't figure out why.
As much as I know, x:foo() is just a syntactic sugar for x.foo(self) but combining this with other classes results in some weird behavior.
Basically, I have two programs
y = {}
function y:bar()
return self.b
end
x = {}
function x:foo()
return y.bar(self)
end
print(x.foo({b = 3}))
This prints 3 as expected
y = {}
function y:bar()
return self.b
end
x = {}
function x:foo()
return y:bar()
end
print(x.foo({b = 3}))
But this prints nil !!
I don't understand, why are these two programs printing different things?
x:foo() is syntactic sugar for x.foo(x)
which means that
function x:foo()
return y:bar()
end
is actually
function x:foo()
return y.bar(y)
end
look again at your use of self
function x:foo()
return y.bar(self) -- = y.bar(x)
end
function x:foo()
return y:bar() -- = y.bar(y)
end
x:foo() is just a syntactic sugar for x.foo(self)
This is correct in the context of a function definition but not as an expression.
function x.y.z:foo(a, b)
print(self, a, b)
end
is the same as
function x.y.z.foo(self, a, b)
print(self, a, b)
end
A function definition being set into a table field can be a method, that is with a :. Nested table fields are also allowed, for methods and non-methods, if the keys are strings that are valid Lua identifiers, as in x.y.z.
But
print(x.y().z:foo(a, b))
is the same as
local _ = x.y().z
print(_.foo(_, a, b))
With the method call syntax, the lefthand-side of : is an expression (x.y().z) that is evaluated only once.
I have the following scenario in which the position of code shall not change. How to modify this code to fix the error without moving the function and table variable. I am a Lua newbie, just 4 days
function a()
print("function a");
end
ftable = {
["a"] = a,
["b"] = b
};
function b()
print("function b");
end
ftable["a"](); -- prints 'function a'
ftable["b"](); -- attempt to call field 'b' (a nil value)
Update : Using the following mechanism its possible to do this.
function a()
print("function a");
end
ftable = {
["a"] = a,
["b"] = "b"
};
function b()
print("function b");
end
ftable["a"](); -- prints 'function a'
_G[ftable["b"]]();
Lua's table declaration and function definition (and function calling syntax) is very flexible. You can use the field key as an identifier instead of the index syntax, provided that the key is a string and is also a valid identifier ({ a = a } and ftable.a()). This seems to be the case with your a and b keys. You can also make the field assignment with the function definition statement (function ftable.b…).
function a()
print("function a")
end
ftable = {
a = a
}
function ftable.b()
print("function b")
end
ftable.a() -- prints 'function a'
ftable.b() -- prints 'function b'
Of course, you could also move "function a" down and code it like "function b". that would leave ftable = { } at the top.
One difference from your code. The global variable b is no longer set to the function. In most cases, this would be considered an advantage.
I would also like to re-iterate what #lhf said,
There are no declarations in Lua, only definitions.
A function definition (in the general case) is an expression. When evaluated, it produces a function value. Various types of statements can assign the value to a variable or field, as does function ftable.b()….
You can't do that. There are no declarations in Lua, only definitions. You need to define variables before using them.
What you can do is to register the names of the functions in ftable and then fix the values before using them:
ftable = {
["a"] = true,
["b"] = true,
}
...
for k,v in pairs(ftable) do ftable[k]=_G[k] end
This code assumes that your functions are defined globally.
There is a piece of code confuses me in Programming in Lua
local iterator -- to be defined later
function allwords ()
local state = {line = io.read(), pos = 1}
return iterator, state
end
function iterator (state)
while state.line do -- repeat while there are lines
-- search for next word
local s, e = string.find(state.line, "%w+", state.pos)
if s then -- found a word?
-- update next position (after this word)
state.pos = e + 1
return string.sub(state.line, s, e)
else -- word not found
state.line = io.read() -- try next line...
state.pos = 1 -- ... from first position
end
end
return nil -- no more lines: end loop
end
--here is the way I use this iterator:
for i ,s in allwords() do
print (i)
end
It seems that the 'for in ' loop call the function iterator implicitly with argument state:
i(s)
Anyone can tell me ,what happened?
Yes. Quoting Lua Manual
The generic for statement works over functions, called iterators. On each iteration, the iterator function is called to produce a new value, stopping when this new value is nil.
The generic for statement is just a syntax sugar:
A for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
do
local f, s, var = explist
while true do
local var_1, ···, var_n = f(s, var)
if var_1 == nil then break end
var = var_1
block
end
end
I know this question seems simple, but I want to know the difference between two ways of creating functions in Lua:
local myFunction = function()
--code code code
end
Or doing this
local function myFunction()
--code code code
end
The difference happens if the function is recursive. In the first case, the "function" name is not yet in scope inside the function body so any recursive calls actually refer to whatever the version of "myFunction" that was in scope before you defined your local variable (most of the times this meas an empty global variable).
fac = "oldvalue"
local fac = function()
print(fac) --prints a string
end
To be able to write recursive functions with the assignment pattern, one thing you can do is predeclare the variable:
local myFunction
myFunction = function()
-- ...
end
Predeclaring variables also happens to be the only way to define a pair of mutually recursive local functions:
local even, odd
even = function(n) if n == 0 then return true else return odd(n-1) end end
odd = function(n) if n == 0 then return false else return even(n-1) end end
The difference is that according to the manual:
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.)
The main reason is that the scope of a variable (where the variable is visible) starts AFTER the local statement, and if a function was recursive, it would not reference itself, but a previous local or a global named f.
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.