I'm creating a dynamic table method reference and trying pass a single param to the method. The dynamic method reference does work and the table method is called just as expected, however the completely not nil param I'm passing to the method is nil inside the method. Can you point out my error in these 2 lines?...
Here is a small working example that demonstrates. On first line in the Consider:Move method, mons is nil
local Consider = {}
function Consider:Move( mons )
print( 'Mons ' .. mons.type .. ' considering Move...')
actionChosen.score = 0
return actionChosen
end
local mons = { type = 'Blue' }
local actionPref = 'Move'
local considerAction = Consider[actionPref]
print( 'MonsterAI:chooseAction mons: ', mons.type )
local actionTest = considerAction( mons )
Functions defined using the colon operator hides an additional first self argument. function Consider:Move(mons) is syntactic sugar for function Consider.Move(self, mons).
Calling the function like considerAction(mons) sets the hidden self argument instead of the desired one.
You might want to pass the Consider table as self:
considerAction(Consider, mons)
Or, alternatively, define the function using the dot operator if you don't need self:
function Consider.Move(mons)
print('Mons ' .. mons.type .. ' considering Move...')
end
Related
hope you having great day , i'm test some stuff with lua, and i got some error
i have this codes in Object.lua
local Object = {name = "Object"}
Object.__index = Object
function Object.new()
local t = setmetatable({}, Object)
return t
end
function Object:keys(table)
local keyset={}
local n=0
for k,v in pairs(table) do
n=n+1
keyset[n]=k
end
return keyset
end
return Object
and i call Object.keys in "Other" script like this
local Object = require("lua.app.common.utils.Object")
local t = {
[1] = a,
[2] = b,
[3]= c
}
Object.keys(t)
and this cause error with
Exception has occurred: bad argument #1 to 'for iterator' (table expected, got nil),
because the parameter 'table' is passed as nil ( i don't know why thuogh debug mode just says its a nil)
on the other hand, if i fix object.keys(table) to object:keys(table), everything works fine, why this error happening?
Declaring the method keys with a colon adds an implicit self parameter as the first argument which requires you to call the method in the same way, using the colon.
Calling the method with the period notation expects you to supply the self parameter but because you only pass in t this is interpreted as self and then nil is added for your table parameter.
Declaring the method with a colon you actually have this
function Object:keys(self, table)
but calling it with the period means you have done this
Object.keys(t, nil)
hence the "table expected, got nil" error
A = {}
function A:text()
return 100
end
print(A["text"]()) -- prints "100"
----------------------------------
A = {}
function A:text(value)
return value
end
print(A["text"](100)) -- prints "nil"
Is there a way that I can pass a value as a parameter and return the same value?I need to loop through 5 functions...
You could, if you declared your function correctly.
function A:text(value)
This creates a function that takes two parameters. The : is what's responsible for that. The first parameter is an implicitly declared parameter called self. The second is value. This function is intended to be called as A:text(100) or with A["text"](A, 100).
These are for class-member-like functions.
You should instead create the function like this:
function A.text(value)
This creates a function that takes one parameter.
As "Nicol Bolas" pointed out, I add table/self parameter and it worked fine.
-- from "A["text"](100)" to "A["text"](self, 100)" or "A["text"](A, 100)"
A = {}
B = {"text", "type"}
function A:text(value)
return "text "..value
end
function A:type(value)
return "type "..value
end
for i=1, 3 do
for j=1, #B do
print(A[B[j]](self, i)) -- prints "text 1 type 1 text 2 type 2 text 3 type 3"
end
end
I ran this code and it gave me an error attempt to index global 'self' (a nil value)
hook.Add("Think", "Cooking", function()
local Position = self:GetPos() + self:GetAngles():Up()*20
local rawFood = ents.FindByName("my_raw_food")
for k, v in pairs(rawFood) do
if(Position:Distance(v:GetPos()) <= 25) then
v:Remove()
timer.Create(self:EntIndex() .. "my_food", 5, 1, function() self:createFood() end)
end
end
end )
It's hard to say without seeing more of the code, especially the scope around your code.
But it sounds like "self" doesn't exist in the scope. Either it should be supplied as a parameter to the function:
hook.Add("Think", "Cooking", function(self)
print(self) -- uses the 'self' parameter
end)
or it should be available in the scope of declaring the function, and it'll be part of the closure:
function MyClass.addHook(self) -- same as MyClass:addHook()
hook.Add("Think", "Cooking", function()
print(self) -- uses the 'self' in scope (la MyClass instace)
end)
Though, self can of course be nil even if it's declared in the scope. Calling MyClassInstance.addHook() instead of MyClassInstance:addHook() is the most common.
self is used when using object oriented programming as described in the documentation 16 - Object-Oriented Programming.
In order to use self you must implicitly pass it as the first argument or not.
I mean...
myObject = { id = 1 }
function myObject:hello( name )
print( "hello " .. name .. " I'm object id : " .. tostring( self.id ) )
end
// Using the . char the object must be the first argument
myObject.hello( myObject, "world" )
// Using the : char the obect is automatically set as the first arg
myObject:hello( "world" )
So in your code, I guess you should use the : char.
hook:add(...)
Can you alias a function (not in a class) in LUA in a similar way to Ruby? In ruby you would do something like this:
alias new_name_for_method method()
def method()
new_name_for_method() # Call original method then do custom code
i = 12 # New code
end
I'm asking because I'm developing for a program that uses LUA scripting and I need to override a function that is declared in a default file.
In Lua, functions are values, treated like any other value (number, string, table, etc.) You can refer to a function value via as many variables as you like.
In your case:
local oldmethod = method
function method(...)
oldmethod(...)
i = 12 -- new code
end
keep in mind that
function method() end
is shorthand for:
method = function() end
function() end just creates a function value, which we assign to the variable method. We could turn around and store that same value in a dozen other variables, or assign a string or number to the method variable. In Lua, variables do not have type, only values do.
More illustration:
print("Hello, World")
donut = print
donut("Hello, World")
t = { foo = { bar = donut } }
t.foo.bar("Hello, World")
assert(t.foo.bar == print) -- same value
FYI, when wrapping a function, if you want its old behavior to be unaffected for now and forever, even if its signature changes, you need to be forward all arguments and return values.
For a pre-hook (new code invoked before the old), this is trivial:
local oldmethod = method
function method(...)
i = 12 -- new code
return oldmethod(...)
end
A post-hook (new code invoked after the old) is a bit more expensive; Lua supports multiple return values and we have to store them all, which requires creating a table:
local oldmethod = method
function method(...)
local return_values = { oldmethod(...) }
i = 12 -- new code
return unpack(return_values)
end
In lua, you can simply override a variable by creating a new function or variable with the same name.
function name_to_override()
print('hi')
end
If you still want to be able to call the old function:
local old_function = name_to_override
function name_to_override()
old_function()
print('hi')
end
I was trying to access a member of 'self', see following:
function BasePlayer:blah()
--do blah
end
function BasePlayer:ctor(tape) --constructor.
self.tape = tape --'tape' is a lua table, and assigned to 'self.tape'.
dump(self.tape) --i can dump table 'self.tape',obviously it's not nil.
self.coreLogic = function(dt) --callback function called every frame.
echoInfo("%s",self) --prints self 'userdata: 0x11640d20'.
echoInfo("%s",self.tape) -- Here is my question: why self.tape is nil??
self:blah() --even function too??
end
end
So my question is, in my callback function 'coreLogic', why 'self.tape' is nil but self is
vaild?
And functions can't be called either.
I'm really confused:S
When you define a function using the :, the implicit parameter is created on its own. When you are defining the function coreLogic, you'd need to pass it as the first argument:
self.coreLogic = function( self, dt )
and that would be the same as:
function self:coreLogic(dt)
self in itself doesn't exist.
Basically,
function BasePlayer:blah()
is same as writing:
function BasePlayer.blah( BasePlayer )