How to correctly redefine print in Lua 5.3? - lua

I frequently use print function for debugging in conjunction with os.exit(). I don't want to type os.exit() each time I use print, so I want to redefine this function.
> function pprint(...)
>> for _,a in ipairs(arg) do
>> print(a)
>> end
>> os.exit()
>> end
> pprint('hello',1,2,3)
hello
1
2
3
[johndoe#dell-john ~]$
Although this works in Lua 5.1, it does not work in Lua 5.3 and, for some reason, Torch. I looked up the Lua 5.3 docs for "triple dots" expression but couldn't find the reference on how to access ... arguments. Can you explain what was changed and how to redefine print for Lua 5.3?

Automatic creation of the arg table for vararg functions was deprecated in Lua 5.1 and removed in Lua 5.2.
As mentioned by Egor, use
for _,a in ipairs({...}) do
instead of
for _,a in ipairs(arg) do
Or add
local arg={...}
at the start of the function.

for _,a in ipairs({...}) do is wrong ,it does not support nil
right rewrite
local arg = table.pack(...)
for i = 1 ,arg.n do
old_print(arg[i])
end

Related

Why Lua's builtin REPL cannot access previously delcared local vars?

See the following example:
$ lua
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> local a = 123
> print(a)
nil
This works as expected:
> local a = 123; print(a)
123
How should I understand the behavior compared to the doc?
The scope of a local variable begins at the first statement after its declaration and lasts until the last non-void statement of the innermost block that includes the declaration.
In the Lua REPL, each (multi)line is loaded as an independent chunk via luaL_loadbuffer. The same system that makes require("mod_a") independent of require("mod_b").
Therefore, the quoted sentence still applies because every time the REPL prints a > (compared to a >> which denotes a multiline) a new block starts, thereby passing the boundary of "the last non-void statement of the innermost block".
Lua REPL treats each line of code as a separate chunk (as if it was a separate Lua file).
When a chunk execution is finished, all its local variables are lost.
So, only global variables are preserved between lines.
Lua REPL is just a REPL, it is not a debugger, where you would be able to watch and modify all variables while program is running.
To use local variables in a multi-line program in Lua REPL: start with do, enter multiple commands, and finally enter end to execute the program you entered.
$ lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> do
>> local a = 123
>> print(a)
>> end
123
>

unwelcome if statement on luajit

lua 5.3.5 accepts the code below,
function isOdd (n)
if n & 1 == 1
then return true
else return false
end
end
print(isOdd(1), isOdd(2))
Why does luajit 2.0.5 refuse it?
line 2: 'then' expected near '&'
Because native bitwise operators are new to Lua 5.3, and LuaJIT is basically Lua 5.1. Use bit.band instead:
This module is a LuaJIT built-in — you don't need to download or install Lua BitOp. The Lua BitOp site has full documentation for all Lua BitOp API functions.
Please make sure to require the module before using any of its functions:
local bit = require("bit")
Source

Why doesn't love2d use my custom-defined pairs metamethod?

I have the following code in the file main.lua:
local table = {data={a=1,b=2,c=3}}
setmetatable(table, table)
function table:__pairs()
return pairs(self.data)
end
function table:__tostring()
return "a table"
end
print(table)
for e in pairs(table) do
print(e)
end
When I run lua main.lua I get the output
a table
a
b
c
When I run love ~/path/to/project I get the output
a table
__tostring
data
__pairs
Why does love use other metamethods correctly, but not pairs?
I have LOVE 11.3 (Mysterious Mysteries) and Lua 5.3.5
Love2D uses LuaJIT as its default interpreter, which is fixed to Lua 5.1. And while you can rebuild Love2D for the standard Lua 5.1 interpreter, making it use modern versions of the standard Lua interpreter would require substantial code hacking, since 5.2+ aren't backwards compatible.
And Lua 5.1 doesn't have the pairs metamethod.

Why can LuaJIT/Openresty use deprecated 'arg' language feature?

My understanding is that LuaJIT uses the Lua 5.1 syntax. In Lua 5.1, the 'arg' feature was removed from the language.
However, the following code works.
// test.lua
local function foo()
for k,v in pairs(arg) do
print(k .. " " .. v)
end
end
foo()
I would expect arg to be nil, but it exists and is doing the Lua 5.0 functionality.
Running resty test.lua hello world results in:
0 test.lua
1 hello
2 world
-1 /usr/local/bin/resty
Why does this work? Are there exceptions to the 5.1 syntax that Openresty and LuaJIT can use?
You're mixing two different things.
The arg table you see here is not a "deprecated Lua feature". It's a table of arguments given to Lua interpreter, explicitly pushed to the global arg variable by the interpreter, and it's still there in the latest Lua and LuaJIT versions.
The feature you've heard was removed - that's about replacing implicit arg parameter with vararg expression in vararg functions. I.e. the extra arguments to functions now available through ... syntax, and not as a table of collected values through implicit arg parameter.

Input to Lua? Just like a console?

I'm trying to make a scripting tutorial for a friend (I'm not too good at it myself but okay) and I'm trying to make it so the input creates an actual line of code that does what they typed. EG:
Input: print("hello")
hello
I understand this is what a console does, but is there any way I can do it with Lua?
Thanks.
just run the lua command to get a lua "REPL":
$ ./lua
Lua 5.3.1 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> print("hello")
hello
>
load
load (ld [, source [, mode [, env]]])
Loads a chunk.
If ld is a string, the chunk is this string.
...
If there are no syntactic errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message.
local input = [[
local args = {...}
print(args[1], args[3]) -- 42 1
return args[1] + args[2], args[2] + args[3]
]]
print(load(input)(42, 99, 1)) -- 141 100
As you can see, the input has access to globals, you can pass values into his code and get the returns.
One way to do this would be using the loadstring function.
Example:
run = loadstring("print('Hello World!'")
run()
Output:
Hello World!

Resources