My question has multiple parts but firstly here is my sample lua code (test.lua):
local traceback = debug.traceback
local inspect = require('inspect')
local foo = "function nop(); print('this is war'); return true; end"
local f = loadstring(foo)
local result = f()
print(result)
local status, val= xpcall(function () return f() end,debug.traceback)
print('status .. ' .. tostring(status))
print(val)
So,
When I run local result = f(). I still see the result value as nil
When the function f is executed. Why don't I see the print o/p .
The chunk of code in foo which you load into f doesn't return any values.
It defines a function but that's it.
If you want to return the function from the chunk when it is run you need to add return nop to the end of the string.
Related
I have this function.
As you can see, I define fn to run a function with arguments provided, how can I check if the amount of arguments that the fn function receives is the amount needed for the function v? Ie, if the user provides 2 args but 3 are needed, throw an error.
ModuleScript:
-- Variables
local dss = game:GetService("DataStoreService")
local db = dss:GetDataStore("greenwich")
-- Tables
local greenwich = {}
local dbFunctions = {}
-- Functions
function greenwich:GetDB(name)
local new = {}
new.name = name
coroutine.resume(coroutine.create(function()
for k, v in pairs(dbFunctions) do
local fn = function(...)
local args = {...}
return v(unpack(new), unpack(args))
end
new[k] = fn
new[string.lower(k)] = fn
end
end))
return new
end
function dbFunctions:Set(store, key, value)
store = store.name
db:SetAsync(store .. key, value)
return value
end
function dbFunctions:Get(store, key)
store = store.name
return db:GetAsync(store .. key)
end
function dbFunctions:Delete(store, key)
store = store.name
local success, val = pcall(function()
return db:RemoveAsync(store .. key)
end)
if val and success then
return true
else
return false
end
end
function dbFunctions:Has(store, key)
store = store.name
return not not db:GetAsync(store .. key)
end
-- Returning everything.
return greenwich
In the standard library of Lua 5.3.5, you can use the debug.getInfo() function to inspect the function. The table that is returned contains a field called nparams which will tell you how many args the function expects.
local example = {}
function example.func(a, b, c)
print(a, b, c)
end
local info = debug.getinfo(example.func)
print(info.nparams) -- 3
In Roblox Lua, which is a custom version based on Lua 5.1, the debug library is heavily modified and you'll need to use the debug.info() function. When you pass in a function and the argument "a", it returns the arity of the function.
local example = {}
function example.funcA(a, b, c)
print(a, b, c)
end
function example:funcB(a, b, c)
print(a, b, c)
end
function example:funcC(a, b, c, ...)
print(a, b, c)
end
-- print out the number of args and whether there's a vararg
print(debug.info(example.funcA, "a")) -- 3 false
print(debug.info(example.funcB, "a")) -- 4 false
print(debug.info(example.funcC, "a")) -- 4 true
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
so i have a lua file analogous to this:
x = { __index = x}
constructor = function()
local o = {}
return setmetatable(o,x)
end
function x:print()
print("hello world")
end
i type the following into the interpretr:
dofile "file.lua"
a = constructor()
a:print() --error attempt to call method 'print' (a nil value)
dofile "file.lua"
a = constructor()
a:print() -- hello world
the method works the second time i import the file but not the first. why is this?
I have tried changing the order (putting the constructor function last) and it was the same.
The first time x is nil. It gets defined and then used the second time.
You need to write x = {}; x.__index = x.
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.
function foo()
return "a", "b", "c"
end
function bar()
return foo()
end
function process()
-- ...
end
function bar_store()
local v = foo()
process()
return v
end
print(bar()) -- A
print(bar_store()) -- B
Result:
a b c -- A
a -- B
How can I make B version act like a A version? In "bar_store" I need to call function than may return any number of return values, but I need to do some work after function call ("process" in my example)
OK, answering your own question is a little bit lame, but:
function bar_store()
local v = {foo()}
process()
return unpack(v)
end