I have two functions that occasionally call each other, and they are local to a module that uses them to build another function. The module is somewhat similar to this piece of code:
local function iseven(n)
if n == 1 then
return false
else
return isodd(n - 1)
end
end
local function isodd(n)
if n == 1 then
return true
else
return iseven(n - 1)
end
end
local evenOrOdd = function(n)
return iseven(n) and "Even" or "Odd"
end
return evenOrOdd
The problem is, when calling evenOrOdd from another file I get the error attempt to call global 'isodd' (a nil value).
I noticed that this doesn't happen if I set iseven to global, but I would like to keep them local to my module.
I even tried putting a dummy function declaration (local function isodd() end) before the line where iseven is declared. I also tried inserting just local isodd in the place of the dummy function declaration, but in both ways it doesn't work and I get different kind of errors.
I know this is because Lua has closures and when iseven is declared it catches the actual value of isodd, which is either nil or the dummy function, and modifying it after doesn't count, but is there a way to bypass this?
The problem is that the call to isodd in iseven uses a global variable, not the local one defined later.
Use forward declarations, as suggested by #Egor:
local iseven, isodd
function iseven(n)
...
end
function isodd(n)
...
end
...
Another way to get past this problem is to use tables. Plain local variables are probably more efficient, but with tables you dont need to manage the declarations.
local T = {}
local function evenOrOdd(n)
return T.iseven(n) and "Even" or "Odd"
end
function T.iseven(n)
-- code
end
The gist of this is that because the table is defined at the top, everything below it has access to it and you can dynamically change it's contents.
When evenOrOdd is called, T.iseven should already be defined by then even though it was not defined when evenOrOdd was defined.
Better check for num%2 - remainder of the division
Related
print("cl_inv wurde geladen!")
concommand.Add("inv_model", function(ply)
local wep = ply:GetActiveWeapon()
if not IsValid(wep) then return end
print(wep:GetWeaponWorldModel())
end)
net.Receive("inv_init", function()
LocalPlayer().inv = {}
end)
net.Receive("inv_give", function()
local classname = net.ReadString()
table.insert(LocalPlayer().inv, classname)
end)
function INV.Open()
local ply = LocalPlayer()
local plyinv = ply.inv
if not ply.inv then return end
local scrw, scrh = ScrW(),ScrH()
INV.Menu = vgui.Create("DFrame")
local inv = INV.Menu
inv:SetSize(scrw * .4, scrh * .6)
inv:Center()
inv:SetTitle("")
inv:MakePopup()
inv.Paint = function(me,w,h)
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(0,0,w,h)
end
local scroll = inv:Add("DScrollPanel")
scroll:Dock(FILL)
scroll.panels = {}
for k,v in pairs(plyinv) do
local itemPanel = scroll:Add("DPanel")
itemPanel:Dock(TOP)
scroll.panels[itemPanel] = true
end
end
hook.Add( "OnPlayerChat", "InvOpen", function( ply, strText, bTeam, bDead )
if ( ply != LocalPlayer() ) then return end
if string.lower(strText) != "!inv" then return end
INV.Open()
end )
I already searched the whole internet for a solution, i did found something but it didnt really helped me so what im expecting is that someone may be so nice and can help me solve my problem. In line 23 is the error :attempt to index global 'INV' (a nil value) (line:23)
As I can see, you're using the Garry's Mod Lua API. Although this API adds some features to the basic Lua language (e.g. ! operator for negation, C-style comments //), you still need to use the Lua language properly.
What the error says, is that you're trying to access to a table that isn't defined in the current scope of your program.
I can bet your addon defined some global table to interoperate between files and other addons installed on your machine.
As I don't have that much information on the way you're loading your file, here are multiple guesses on possible solutions:
For a file located inside an autorun folder
If the snippet you gave is under an autorun folder, the issue may be that the INV table does not yet exist when you load your file. To correct that, you can use the GLua Timer's Library.
Here is a simple snippet:
Timer.Simple(0.2, function()
-- put your code here
end
Timer.Simple takes two parameters: first one is a delay, in seconds and the other one is a callback function, executed once the delay has ended !
If you're doing something that requires the server to have loaded some other addons before actually running your script, this might be helpfull.
Accessing Global variables of your environment
As you did not gave that many informations about your problem I have to continue to guess what you're trying to do. An other source of problem is maybe that the INV table simply doesn't exist.
How to get all defined global tables in Lua ?
In Lua, there is the _G table that contains all the data of your current environnement. For more in-depth information, please see the official Lua documentation.
To know if your table does in fact exist in your environment, you can run this snippet on your Lua server:
local function doesINVExist()
for name in pairs(_G) do
if (name == "INV") then return true end
end
return false
end
And then you can simply run it using:
print(doesINVExist())
What to do if the table doesn't exist
If INV isn't present in your environment, then it may be because your Garry's Mod server did not loaded any file that defines such a table. Then what you can do is checking the addon that should dclare that table to see if there are any errors that might make it a nil value.
I hope this can help. Of course my answer could've been much more detailed if I had more information. But as I can't write comments (my rating isn't high enough), here is all I can do for you !
Have a great day,
Pedro.
I'm trying to figure out a way to get all functions in a Lua script. This script has been compiled into a function through loadfile. For example, I'd want to get every function defined in the script below.
function example1()
end
local function example2()
end
local library = {}
function library:example3()
end
(function()
-- Functions like this too.
end)
The names aren't important, I'm just looking for a way to get the actual functions so I can use them in debug.getinfo and get information like the lines they were defined in. I have LuaJIT, if that makes this any easier. Is something like this even possible? Thanks in advance.
I guess the file declares its functions as global, or it would be really easy to track what is returned.
If that's the case, you can cycle through all the global items with a generic for loop, and only take the functions from them:
allFuncs = {}
for key, item in pairs(_G) do
if type(item) == "function" then
allFuncs[#allFuncs + 1] = item
end
end
(_G is the table holding all the global variables)
Then you will have a list (allFuncs) holding all the functions declared, but be aware that it will also contain default functions like setmetatable or xpcall.
It's easy to modify the code to not make this happen, but only use this for testing / learning:
function allFuncs()
local funcsTab = {}
for key, item in pairs(_G) do
if type(item) == "function" then
funcsTab[#funcsTab + 1] = item
end
end
return funcsTab
end
defaultFuncs = allFuncs()
--then you load your file: other functions get declared
--we create another table containg the default + the new functions
myFuncs = allFuncs()
--then you subtract the first table from the second
for i = 1, #myFuncs do
for o = 1, #defaultFuncs do
if myFuncs[i] == defaultFuncs[o] then
table.remove(myFuncs, i)
end
end
end
This is if your file doesn't return anything and declares its functions as globals.
If the file declares them as local and then returns a table containing them, just use the first piece of code replacing _G with that returned table.
This is not likely to be possible without syntax or bytecode analysis as each function definition is an assignment (just has different forms in your examples). See the bytecode inspector and a related discussion here. For the syntax analysis you can use metalua or something like lua-loose-parser. Keep in mind that even those tools won't give you the entire list of functions as some functions may be defined dynamically using loadstring (or similar methods).
If you only have access to the result of loadfile, then you best bet is to use the bytecode analyzer.
This is possible using jit.attach in LuaJIT.
You can attach callbacks to a number of compiler events with
jit.attach. The callback can be called:
when a function has been compiled to bytecode ("bc");
when trace recording starts or stops ("trace");
as a trace is being recorded ("record");
or when a trace exits through a side exit ("texit").
http://wiki.luajit.org/JIT-Compiler-API#jit-attach
jit.attach(function(f)
local funcInfo = jit.util.funcinfo(f)
end, "bc")
I have an object that I create using the following function
local function newObject(functionVariable)
...
functionVariable = functionVariable or nop
...
return setmetatable({
...
functionVariable = functionVariable,
...
}, Objectmt)
end
When I deepcopy this object using this
local function deepcopy(t)
if t == nil then return nil end
if type(t) == 'table' then
local copy = {}
for k, v in pairs(t) do
copy[k] = deepcopy(v)
end
setmetatable(copy, deepcopy(getmetatable(t)))
return copy
else -- number, string, boolean, etc
return t
end
end
and load in the object using this
for k, v in pairs(state.objectsTable) do objectsTable[k] = v end
the function variable is totally wrong. It isn't the function that was passed into the object anymore and yeilds unexpected results
There are a lot of things that could be going wrong, and not enough information to say for sure. However, there are some things I can see that could be wrong with your copy, and one in particular that seems problematic.
Your deepcopy function will copy the metatable of the object:
-- snip...
setmetatable(copy, deepcopy(getmetatable(t)))
-- ...
However, it is a fairly common practice for objects of the same type to share the same metatable, and moreover, your code seems to do this (although without seeing how Objectmt is defined, it isn't clear). Other code can then, for example, determine if something is an object by doing:
function isObject(obj)
return getmetatable(obj)==Objectmt
end
This will fail for your copy, because the metatable is no longer the same (even if it has the same contents).
This could be fixed by having a different version of deepcopy (or modifying the existing one) to reuse the metatable:
-- snip...
setmetatable(copy, getmetatable(t))
-- ...
If that is not the problem, then are are some other things to consider:
Your deepcopy function does not copy table keys. In some cases copying keys could be important, but that doesn't seem to be the case for any of the code you've shown.
Your deepcopy function will not copy functions. This could be important if you use functions with mutable upvalues. Again, this isn't the case for any of the code you've shown.
It is possible that there are other tables besides the metatable that ought to be copied by reference rather than by value. To know which is appropriate, you must understand the way they are used.
There could be userdata or other less common types (e.g. coroutines) that are currently being copied by reference that would need to be copied by value. Some things might not be copyable by value.
There might be something in the data you are copying that ought not by copied at all, for example, a unique identifier.
The problem might not be with the copy at all.
I have a function I want to add to dynamically as the program runs.
Let's say I have function Foo:
function foo()
Function1()
Function2()
Function3()
end
and I want to change Foo() to:
function foo()
Function1()
Function2()
Function3()
Function4()
end
later in the program. Is there any way to do this?
Just do it. The code that you wrote works fine. Functions in Lua can be redefined as desired.
If you don't know what foo does, you can do this:
do
local old = foo
foo = function () old() Function4() end
end
Or perhaps it is clearer to use a table of functions:
local F={ Function1, Function2, Function3 }
function foo()
for i=1,#F do F[i]() end
end
Latter, do
F[#F+1]=Function4
and you don't need to redefine foo.
This is a supplementary answer with background information.
Lua identifiers are used for global variables, local variables, parameters and table fields. They hold any type of value.
Lua functions are values. Lua functions are all anonymous, regardless of the syntax used to define them.
function f()
--...
end
is a Lua statement that compiles to a function definition and an assignment to a variable. It's an alternate to
f = function()
--...
end
Each time a function definition is executed, it produces a new function value, which is then used in any associated expression or assignment.
It should be clear that neither statement necessarily creates a new variable nor requires it to always have the same value, nor requires it to always hold a function value. Also, the function value created need not always be held only by the one variable.
It can be copied just like any other value.
Also, just like other values, function values are garbage collected. So, if f had a function value and is assigned a different value or goes out of scope (say, if it wasn't a global variable), the previous value will be garbage collected when nothing else refers to it.
Without any other context for function f() end, we would assume that f is a global variable. But that's not necessarily the case. If f was an in-scope local or parameter, that is the f that would be assigned to.
I am writing program in Octave and I encountered a problem, I implemented Gauss-Legandre Quadrature and I pass to my Gauss-Legandre function few arguments, and I pass the function to be intergrated in a cell cube, so I can pass few function at a time. I have this piece of code:
for weight=1:length(w)
temp=1;
for fun=1:length(c)
%liczenie iloczynu f(x_i)g(x_i), x_i - pieriwastki wielomianu Legandra
f=c{fun};
nargin(func2str(c{fun}))
if (nargin (func2str(c{fun})) == 1)
disp('a');
temp*=c{fun}((b-a)/2 * x(weight) + (a+b)/2);
else
(b-a)/2 * x(weight) + (a+b)/2;
temp*=f((b-a)/2 * x(weight) + (a+b)/2,I,points);
end
end
%mnozenie wyniku przez odpowiedni wspolczynnik - wage
temp*=w(weight);
result+=temp;
end
In cell array there are function handlers to functions which I want to integrate. Depending on number of arguments that function takes i want to use two different calls for function. If in cell array there is handler to a function that is written in .m file in the same directory as my Octave working directory everything works fine, but when i define function in Octave running time, for example:
function result=a(x)
result=x*x
end
Type
c{1}=#a
and pass this cell array to my function Kwadratury there is an error of nargin
error: nargin: invalid function
error: called from:
Why is that and how can I solve it, so I can define function not only in .m files but also in Octave.
I suspect I have a solution, but as this is Octave-specific and I'm mostly used to MATLAB, your mileage may vary.
You call the nargin function by supplying a string argument, this means that nargin will have to resolve that function and check the number of arguments. When you declare a function in-line, that function is defined within that scope (i.e. your base scope), so resolving the function name will not work from within any function (or it might resolve to a built-in function, which is even worse behavior).
The best solution is to use nargin(c{fun}) instead of nargin(func2str(c{fun})). That way you pass the actual function handle along, and there is no need to resolve the function name to the actual function, and hence no possible ambiguity.
In general I recommend against using strings to pass functions: that why function handles are included in MATLAB, so anyone reading your code (or a static code analysis tool) will be able to understand you are working with functions. When using strings, everything becomes ambiguous: does a string 'a' refer to the function a or to the first letter in the alphabet?
With regard to using inline functions, I don't know whether Octave supports this, but if you function is quite simple, it's easier to define an anonymous function, such as your example, by a = #(x)(x*x);. That is a construct that is supported by MATLAB, so that makes your code more portable to other environments (well, you'd still need to replace X *= A with X = X * A; to be MATLAB compatible).
edit:
Another possibility could be to just try out whether a form with multiple parameters works and fall back to the one parameter form when necessary:
try
(b-a)/2 * x(weight) + (a+b)/2;
temp*=f((b-a)/2 * x(weight) + (a+b)/2,I,points);
catch ME
try
disp('a');
temp*=c{fun}((b-a)/2 * x(weight) + (a+b)/2);
catch ME
end
end
You might want to check whether the returned error ME really states that a wrong number of arguments is used to allow other errors through. I do admit this is an ugly work-around, but since Octave apparently doesn't support function handles for nargin, it might be the only way you'd get what you want for inline functions.