understanding how a lua function does work? - function

I have a HTML project that uses mutiple lua scripts , I have big issue unterstanding the functionality of one function ( I'm new to lua) :
........................
all the requires have been done and the paths are also defined
local fs = require "lfs"
local const = {}
for num = 1, 14 do
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant configuration ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)-- when I print num is 0 and ci,co are nil
local vi, vo, _ = fs.dir(virt_path)-- what does _ mean here ?
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)---where is ci defined or impplemented
end
return iter, {co=co, vo=vo}, num-- what 's the return value here ?
end
the function works but I still don't understand why and how, I 'll be greatfull for any hint.

_ is conventionally a throw-away variable.
In this case though it serves no purpose and could just as easily be left out entirely.
ci should be a function and co should be a table there.
Similarly (though I can't say for sure about vo) for vi and vo.
That function is constructing its own iterator using the iterator functions and state returns from the ipairs and fs.dir functions.
The line return iter, {co=co, vo=vo}, num is returning an interator function, a table for state, and the initial loop variable (0 from the initial ipairs call).
When used in a loop that will loop over the values from ci and vix.

Related

Decode and Parse JSON to Lua

I have following JSON data I would like to decode to Lua to access each the publish_topic and sample_rate value.
{"00-06-77-2f-37-94":{"publish_topic":"/stations/test","sample_rate":5000}}
If I understand correctly the Lua table will look like this:
{00-06-77-2f-37-94 = "publish_topic":"/stations/test","sample_rate":5000}
Next I would go through the table to save each value into a local variable.
However, if I try printing out the values of the table (using following code), I get 'nil' as return. Is the code for reading table values wrong?
Does the table have two values or is it just the one: ["publish_topic":"/stations/test","sample_rate":5000] ?
lua_value = JSON:decode(data)
for _,d in pairs(lua_value) do
print(lua_value[d])
end
local topic = lua_value[0]
local timer = lua_value[1]
end
Edit: I am using following JSON library for Lua: http://regex.info/blog/lua/json
Edit2: #Piglet: I implemented your script and modified it by adding a table (conversionTable) in which both elements "publish_topic":"/stations/test" and "sample_rate:5000" would be respectively saved in the variables pubtop and rate. When I however print each of both variables, nil ist returned in both cases.
How can I extract the information out of this table to save in variables?
Ultimately I actually only would like to save the values "/stations/test" and "5000" into these variables. Would I need to parse each of the elements above to get these or is there another way?
local pubtop
local rate
local function printTable(t)
local conversionTable = {}
for k,v in pairs(t) do
if type(v) == "table" then
conversionTable [k] = string.format("%q: {", k)
printTable(v)
print("}")
else
print(string.format("%q:", k) .. v .. ",")
end
end
pubtop = conversionTable[0]
rate = conversionTable[1]
end
local lua_value
local function handleOnReceive(topic, data, _, _)
print("handleOnReceive: topic '" .. topic .. "' message '" .. data .. "'")
-- This sample publishes the received messages to test/topic2
print(data)
lua_value = JSON:decode(data)
printTable(lua_value)
print(pubtop)
print(rate)
end
client:register('OnReceive', handleOnReceive)
I don't know which json library you're using so I can't tell you wether JSON:decode(data) is the correct way.
Assuming lua_value would like like so:
local lua_value = {
["00-06-77-2f-37-94"] = {
publish_topic = "/stations/test",
sample_rate = 5000
}
}
Then your loop
for _,d in pairs(lua_value) do
print(lua_value[d])
end
will indeed print nil.
lua_value has a single element at key "00-06-77-2f-37-94" which is a table.
Each loop iteration will give you a key value pair. So d is actually the value and hence the inner table of lua_value
So you're actually doing this:
local innerTable = lua_value["00-06-77-2f-37-94"]
print(lua_value[innerTable])
Of course lua_value[innerTable] is nil.
Edit:
Try something like
function printTable(t)
for k,v in pairs(t) do
if type(v) == "table" then
print(string.format("%q: {", k))
printTable(v)
print("}")
else
print(string.format("%q:", k) .. v .. ",")
end
end
end
printTable(lua_value)

Is it possible to figure out the return value of a function in lua? Or whether or not a function returns anything?

Lets say for example I have made a function and it's purpose is to analyze another function supplied as a parameter and return whether or not the function specified will return anything, and if so what value it will return.
local function CheckFunctionReturn(func)
--return whether func would return anything.
end
local function myFunc()
return 123;
end
CheckFunctionReturn(myFunc);
I am stuck with this. Perhaps there is a function in the debug library that can help? I would appreciate any help.
None of the functions in the debug library can do this. Instead you need to analyse the source code or the bytecode to find out what the program will do. There are some resources available on the Lua wiki, and others have given good suggestions above as well.
Note that the problem of whether an arbitrary function will return or not when it is given arbitrary input is the halting problem, and was proven to be impossible to solve in the general case by Alan Turing back in 1936. However, for simple functions and/or inputs it is solvable, so if your specific case is simple enough you might be able to do it.
This is quick-and-dirty solution (only Lua 5.1, only LE architecture), which is likely to work in most cases, but not always.
It only answers the question "Whether or not this function would return some values?"
local function CheckFunctionReturn(func)
-- returns true if func would return anything
local d = string.dump(func)
assert(d:sub(1,5) == "\27LuaQ") -- only Lua 5.1
-- search for code before first "return" (0x0080001E)
d = d:match"^.-\30%z\128%z"
-- search for "return" with non-zero number of returned values
for pos = #d % 4 + 1, #d, 4 do
local b1, b2, b3, b4 = d:byte(pos, pos+3)
local dword = b1 + 256 * (b2 + 256 * (b3 + 256 * b4))
local OpCode, BC = dword % 64, math.floor(dword/16384)
local B, C = math.floor(BC/512), BC % 512
if OpCode == 30 and C == 0 and B ~= 1 then
return true
end
end
return false
end
print(CheckFunctionReturn(aFunctionToBeAnalyzed));
local function CheckFunctionReturn(func)
print(type(func()))
end
local function myFunc()
return 123;
end
CheckFunctionReturn(myFunc);
Am I missing something?
The Lua built-in debug API docs says
The return hook: is called when the interpreter returns from a function. The hook is called just before Lua leaves the function. There is no standard way to access the values to be returned by the function.

Composing two functions in lua

I just started learning lua, so what I'm asking might be impossible.
Now, I have a method that accepts a function:
function adjust_focused_window(fn)
local win = window.focusedwindow()
local winframe = win:frame()
local screenrect = win:screen():frame()
local f, s = fn(winframe, screenrect)
win:setframe(f)
end
I have several functions that accept these frames and rectangles (showing just one):
function full_height(winframe, screenrect)
print ("called full_height for " .. tostring(winframe))
local f = {
x = winframe.x,
y = screenrect.y,
w = winframe.w,
h = screenrect.h,
}
return f, screenrect
end
Then, I can do the following:
hotkey.bind(scmdalt, '-', function() adjust_focused_window(full_width) end)
Now, how could I compose several functions to adjust_focused_window, without changing it's definition. Something like:
hotkey.bind(scmdalt, '=', function() adjust_focused_window(compose(full_width, full_height)) end)
where compose2 would return a function that accepts the same parameters as full_width and full_height, and internally does something like:
full_height(full_width(...))
As mentioned in the comments, to chain two functions together you can just do:
function compose(f1, f2)
return function(...) return f1(f2(...)) end
end
But what if you want to connect more than 2 functions together? You might ask, is it possible to 'compose' an arbitrary number of functions together?
The answer is a definite yes -- below I show 3 different approaches for implementing this plus a quick summary of their consequences.
Iterative Table approach
The idea here is to call each function in the list one after the other in turn. While doing so, you save the returned results from the previous call into a table and you unpack that table and pass it into the next call.
function compose1(...)
local fnchain = check_functions {...}
return function(...)
local args = {...}
for _, fn in ipairs(fnchain) do
args = {fn(unpack(args))}
end
return unpack(args)
end
end
The check_functions helper above just checks that the stuff passed in are indeed functions -- raises an error if not. Implementation omitted for brevity.
+: Reasonably straight-forward approach. Probably what you'd come up with on a first attempt.
-: Not very efficient on resources. A lot of garbage tables to store results between calls. You also have to deal with packing and unpacking the results.
Y-Combinator Pattern
The key insight here is that even though the functions we're calling isn't recursive, it can be made recursive by piggy-backing it on a recursive function.
function compose2(...)
local fnchain = check_functions {...}
local function recurse(i, ...)
if i == #fnchain then return fnchain[i](...) end
return recurse(i + 1, fnchain[i](...))
end
return function(...) return recurse(1, ...) end
end
+: Doesn't create extra temporary tables like above. Carefully written to be tail-recursive -- that means no extra stack space needed for calls to long function chains. There's a certain elegance to it.
Meta-script generation
With this last approach, you use a lua function that actually generates the exact lua code that performs the function call chain desired.
function compose3(...)
local luacode =
[[
return function(%s)
return function(...)
return %s
end
end
]]
local paramtable = {}
local fcount = select('#', ...)
for i = 1, fcount do
table.insert(paramtable, "P" .. i)
end
local paramcode = table.concat(paramtable, ",")
local callcode = table.concat(paramtable, "(") ..
"(...)" .. string.rep(')', fcount - 1)
luacode = luacode:format(paramcode, callcode)
return loadstring(luacode)()(...)
end
The loadstring(luacode)()(...) probably needs some explaining. Here I chose to encode the function chain as parameter names (P1, P2, P3 etc.) in the generated script. The extra () parenthesis is there to 'unwrap' the nested functions so the inner most function is what's returned. The P1, P2, P3 ... Pn parameters become captured upvalues for each of the functions in the chain eg.
function(...)
return P1(P2(P3(...)))
end
Note, you could also have done this using setfenv but I chose this route just to avoid the breaking change between lua 5.1 and 5.2 on how function environments are set.
+: Avoids extra intermediate tables like approach #2. Doesn't abuse the stack.
-: Needs an extra byte-code compile step.
You can iterate through the passed functions, successively invoking the next function in the chain with the results from the previous.
function module._compose(...)
local n = select('#', ...)
local args = { n = n, ... }
local currFn = nil
for _, nextFn in ipairs(args) do
if type(nextFn) == 'function' then
if currFn == nil then
currFn = nextFn
else
currFn = (function(prev, next)
return function(...)
return next(prev(...))
end
end)(currFn, nextFn)
end
end
end
return currFn
end
Note the use of Immediately Invoked Function Expressions above, which allow the re-used function variables to not invoke an infinite recursive loop, which happens in the following code:
function module._compose(...)
local n = select('#', ...)
local args = { n = n, ... }
local currFn = nil
for _, nextFn in ipairs(args) do
if type(nextFn) == 'function' then
if currFn == nil then
currFn = nextFn
else
currFn = function(...)
return nextFn(currFn(...)) -- this will loop forever, due to closure
end
end
end
end
return currFn
end
Although Lua doesn't support ternary operators, short-circuit evaluation can be used to remove the inner if statement:
function module.compose(...)
local n = select('#', ...)
local args = { n = n, ... }
local currFn = nil
for _, nextFn in ipairs(args) do
if type(nextFn) == 'function' then
currFn = currFn and (function(prev, next)
return function(...)
return next(prev(...))
end
end)(currFn, nextFn) or nextFn
end
end
return currFn
end

Lua - find out calling function

In Lua, is it possible to know which function has called the current function.
For instance
function a()
get_calling_function() --Should print function b
end
function b()
a()
end
Is something like this possible?
Does the debug library have such functionality?
You could use debug.traceback():
function a()
print(debug.traceback())
end
function b()
a()
end
b()
which would print:
stack traceback:
./test.lua:45: in function 'a'
./test.lua:50: in function 'b'
./test.lua:53: in main chunk
[C]: in ?
you can use debug.sethook() to set up a hook that gets called each time certain special events happen in lua. it can be useful for things like this.
local debugInfo = { caller = nil, callee = nil }
function hook()
local info = debug.getinfo(2)
if info == nil then
debugInfo.callee = nil
return
end
-- we only want to watch lua function calls (not C functions)
if info.what ~= "Lua" then
debugInfo.callee = "C function"
return
end
debugInfo.caller = debugInfo.callee
debugInfo.callee = info.name
end
debug.sethook(hook, "c")
function caller1()
if debugInfo.caller ~= nil and debugInfo.callee ~= nil then
msg = debugInfo.callee.. " was called by ".. debugInfo.caller.. "!"
print(msg)
end
end
function caller2()
caller1()
end
caller2()
this prints 'caller1 was called from caller2!'
debug.sethook can handle 3 different characters in the second parameter so you can let it know when to notify you. 'c' means call your hook function any time a function is called in lua, 'r' means call your hook function every time a function returns in lua, and 'l' means call your hook function whenever lua processes a new line of code.
you could set this up to build your own custom stack trace if you really wanted to, and you could also use debug.getlocal() within your hook to even try to work out what arguments were passed to your called function.
edit for lhf. this is actually a much simpler way of doing what you're asking, if you don't need to track this and just need to know the context of how the function was called.
function caller1()
local current_func = debug.getinfo(1)
local calling_func = debug.getinfo(2)
print(current_func.name.. " was called by ".. calling_func.name.. "!")
end
function caller2()
caller1()
end

Difference between . and : in Lua

I am confused about the difference between function calls via . and via :
> x = {foo = function(a,b) return a end, bar = function(a,b) return b end, }
> return x.foo(3,4)
3
> return x.bar(3,4)
4
> return x:foo(3,4)
table: 0x10a120
> return x:bar(3,4)
3
What is the : doing ?
The colon is for implementing methods that pass self as the first parameter. So x:bar(3,4)should be the same as x.bar(x,3,4).
For definition it is exactly the same as specifying self manually - it will even produce same bytecode on compilation. I.e. function object:method(arg1, arg2) is same as function object.method(self, arg1, arg2).
On use : is almost the same as . - a special kind of call will be used internally to make sure object and any possible side-effects of calculations/access are calculated only once. Calling object:method(arg1, arg2) is otherwise same as object.method(object, arg1, arg2).
To be completely precise, obj:method(1, 2, 3) is the same as
do
local _obj = obj
_obj.method(_obj, 1, 2, 3)
end
Why the local variable? Because, as many have pointed out, obj:method() only indexes _ENV once to get obj. This normally just important when considering speed, but consider this situation:
local tab do
local obj_local = { method = function(self, n) print n end }
tab = setmetatable({}, {__index = function(idx)
print "Accessing "..idx
if idx=="obj" then return obj_local end
end})
end
tab.obj.method(tab.obj, 20)
--> Accessing obj
--> Accessing obj
--> 20
tab.obj:method(10)
--> Accessing obj
--> 10
Now imagine the __index metamethod did more than just printing something. Imagine it increased a counter, logged something to a file or deleted a random user from your database. There's a big difference between doing that twice or only once. In this case, there's a clear difference between obj.method(obj, etc) and obj:method(etc).