I'm playing with this lua link: http://underpop.free.fr/l/lua/docs/programming-in-lua-first-edition.pdf and get confused about the rename function. I tried it out and only to get an error message as the following.
> rename{old = "temp.lua", new = "temp1.lua"}
stdin:1: attempt to call global 'rename' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
> os.rename{old = "temp.lua", new = "temp1.lua"}
stdin:1: bad argument #1 to 'rename' (string expected, got table)
stack traceback:
[C]: in function 'rename'
stdin:1: in main chunk
[C]: in ?
Moreover, I'm learning Lua because I'm reading a piece of code, which is written in Lua. I do not think the link provided above, programming in lua first edition, is a good tutorial. I've also found a reference menu, but do not quite like it also. Can anyone please provide a good tutorial based on your opinion?
EDIT: I tried it again with the following code:
> function rename(arg)
>> return os.rename(arg.old, arg.new)
>> end
>
> rename{old = "temp.lua", new = "temp1.lua"}
It works this time.
stdin:1: attempt to call global 'rename' (a nil value)
This error message tells you exactly what the problem is.
It is caused by this line:
rename{old = "temp.lua", new = "temp1.lua"}
rename is a nil value. Hence Lua does not know what to do if you call it. In order to avoid this error you have to define rename as a callable variable like.
Let me just quote the tutorial you do not find good.
rename{old="temp.lua", new="temp1.lua"}
Accordingly, we define rename with only one parameter and get the
actual arguments from this parameter:
function rename (arg)
return os.rename(arg.old, arg.new)
end
Related
I have this code right here, in a file named "hframe.lua".
table.insert(handler.class, framename)
local func = [[
function new(())
print("Hello Stackoverflow!")
end
]] --The function test itself.
local a="table.insert(handler.class."..framename..", "..func..")" --I broke it in two to make things easier for me to read.
print(a) --Read out the variable so I can see what it looks like.
local b=load(a) --Load it up
b() --Nil error. Great.
"framename" is a constant from another file, which is simply declared as "frame". The error is a simple nil error. Upon running b(), it throws a local nil error. With an assert, I've discovered this error.
Error: Thread error (Thread: 0x04c7d2f0)
uicode/hframe.lua:16: [string "table.insert(handler.class.frame, function ne..."]:1: '(' expected near 'new'
stack traceback:
[C]: in function 'assert'
uicode/hframe.lua:16: in main chunk
[C]: in function 'require'
uicode/handlerthread.lua:165: in main chunk
stack traceback:
[string "boot.lua"]:777: in function <[string "boot.lua"]:773>
[C]: in function 'error'
[string "boot.lua"]:631: in function <[string "boot.lua"]:630>
[string "boot.lua"]:604: in function <[string "boot.lua"]:594>
[C]: in function 'xpcall'
I'm not entirely sure WHY it's throwing this error, because clearly I define it as function new(). What I have I done wrong?
function new() end
is syntactic sugar for
new = function () end
This is an assignment. It does not resolve to a value. Hence you cannot use a function definiton where a value is expected.
In your case the code executed is
table.insert(handler.class.someFrameName,
function new () print("Hello Stackoverflow!") end
)
The only thing that would make sense for Lua with the function keyword present in a list of expressions is an anonymous function and it expects a ( after function but finds new
You have two options to fix this.
If function new() end is equivalent to new = function () end, function () end must resolve to a function value. So we can create a function value in-place:
table.insert(handler.class.someFrameName,
function () print("Hello Stackoverflow!") end
)
I'll leave it up to you to impelement this in the string you want to load.
Another option is to define the function first. You can do this both in the string or in the scope of your load call.
function new() print("Hello Stackoverflow")
table.insert(handler.class.someFrameName, new)
Lua load() function returns nil and the error if it failed to compile code. Since the passed code is invalid, b is nil. Therefore a error is raised when you attempt to call it.
The reason the code is invalid is because when a function declaration is used as an expression, the function name must be omitted, e.g.
table.insert(sometable, function() … end)
Please note that most likely you don’t need to create code dynamically, the following will work:
table.insert(handler.class[framename], function() … end)
i'm new in lua programming. Trying to make a game based on platforms and physics. I couldn't get the probem. Please help. :( This is the part i get an error:
for i, obj in pairs(gameMap.layers["Platforms"].objects) do
spawnPlatform(obj.x, obj.y, obj.width, obj.height)
end
and this is the error code:
Error
main.lua:25: attempt to call global 'spawnPlatform' (a nil value)
Traceback
main.lua:25: in function 'load'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
I tried to add a function to the Module.lua abstract file in the Torch package called nn, but my main program does not find it.
Suppose my function is simply:
function printTry()
print("printTry()");
end
I added this function at the end of the Module.lua file and I was supposed to use it in my Torch terminal:
require 'nn';
perceptron = nn.Module();
perceptron:printTry()
But the system generates:
string "perceptron.printTry();"]:1: attempt to call field 'printTry' (a nil value)
stack traceback:
[string "perceptron.printTry();"]:1: in main chunk
[C]: in function 'xpcall'
/home/davide/torch/install/share/lua/5.1/trepl/init.lua:668: in function 'repl'
...vide/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:199: in main chunk
[C]: at 0x004064d0
Probably the system is not aware of this new function that I added... what should I do to use this new method?
Use torch.getmetatable:
require 'nn'
torch.getmetatable('nn.Module').printTry = function() print('PrintTry') end
perceptron = nn.Sequential()
perceptron:printTry()
You simply defined a global function printTry, but you call it as a method on perceptron. You need to define it as a field of Module (in that Module.lua file, assuming this is what nn.Sequential returns):
function Module:printTry()
print("printTry()")
end
Let's say that I call some functions indirectly, via a variable. For example:
obj = {
on_init = function()
print "hello."
end,
on_destroy = function()
print "bye."
end,
on_do_something = function()
print "doing something."
error("Hi de hi, hi de ho!")
end,
}
local event = "do_something"
local func = obj["on_" .. event]
func()
All works fine.
However, the problem is that when the called function raises an exception (as in the code above) the error message isn't quite clear. It is thus:
lua: test.lua:13: Hi de hi, hi de ho!
stack traceback:
[C]: in function 'error'
test.lua:13: in function 'func'
test.lua:20: in main chunk
It says "in function 'func'". I'd prefer it to say "in function 'on_do_something'" instead.
I'd imagine this scenario to be very common. Is there a solution for this?
I tried calling the function thus:
obj["on_" .. event]()
But then the error message says "in function '?'", which isn't helpful either.
(I tried this code on Lua 5.1, 5.2 and LuaJIT without notable differences.)
This is a limitation of the heuristics used by Lua to provide names for functions.
In Lua, all functions are anonymous. A given function can be the value of several variables: global, local, and table fields. The Lua debug system, which is used in error handling, tries to find a reasonable name for a value based on where it came from by looking into the bytecode being executed.
See
Why is 'name' nil for debug.getinfo(1).
You have a few options. The debug module will try to produce something useful. For instance, you might be able to get the file name and line number where it was defined, if this is your own code. See
http://www.lua.org/pil/23.1.html for the list of what is available via debug module. Or, you might be able to define the functions in the module, then add them to the table:
-- module something
function a()
...
end
tt = {
fn1 = a,
...
}
Depending on where you trap the error (error handler installed via debug hook?), you could check if filename is the module where your table of functions is defined, and if it is, then use the debug module to print appropriate info based on your table structure etc; if it is not, just print the default traceback etc.
The code says it all:
#tryModA.lua:
f,err=loadfile("tryModB.lua")
if not f then
print("F is nil!!! Err:"..err)
else
f.fn=function (x)
print("x="..x)
end
f()
end
And here is the loaded file:
#tryModB.lua:
fn("hello")
Error:
lua: tryModA.lua:7: attempt to index global 'f' (a function value)
stack traceback:
tryModA.lua:7: in main chunk
[C]: ?
Question: why does it happen ?
Isn't it true that loadfile() returns a function object and I can attach another function to it? PS. I come from a JavaScript programming background where it has prototype-based objects. I assume Lua has the same prototype based objects.
In Lua, loadfile() returns a function (not a function object) and functions can only be called. "Attaching" whatever to a function like you are trying is not possible.
Now, Lua tables are completely different story and the prototype-based concepts from JavaScript probably apply to them (I'm not very familiar with JS). The simplest way to make your code work at this point is to make fn global i.e. replace f.fn = function... with fn = function... although this might not be what you want.