Shared Table not printing on Client - lua

Basically I have a SHARED lua file where I define the table.
I did this because I thought if we define the Table in a shared file we can use it client and server side.
SHARED.lua:
TableA = {}
Then I edit it on a SERVER lua file.
SERVER.lua:
function UpdateTable()
// Clean Table first
for k in pairs(TableA) do
TableA[k] = nil
end
... not worth showing the rest ...
// Insert New Values
for i=1, 10 do
table.insert(TableA, result[i])
end
// Debug Print
print(table.ToString(TableA)) // It Prints every value correctly
end
Now when I try to print it client side, it says the Table exists but it's empty.
CLIENT.lua:
print(table.ToString(TableA))// Prints "{}" and it shouldn't be empty
Note: UpdateTable() runs every 5min

Apparently when we define a table shared, doesn't mean the values will be shared through the server and client. It only means that the code will run on both server/client.
You have to network them for them to "share" the values on the table.

Related

Attempt to call global (a nil value) - when saving tables to a file with Lua

I'm using this (old) Lua module to save and access tables from local files (if there is a better way, please shout I'm not invested) -- https://github.com/gideros/table.save/blob/master/table.save-0.94.lua
It's been working great, but now I'm trying to save key value pairs I'm getting the error:
attempt to call global exportstring (a nil value)
I'm new to Lua. The error is on line 108 on that file I linked to. Any ideas?
I've tried creating blank tables, or basic tables without key value pairs, this works fine. It's when I come to insert strings the issues arise.
This will work:
local myTable = {}
myTable[0] = 2
inputOutputTable.save(myTable, "testytesty")
local testy = inputOutputTable.load("testytesty")
print("Testing 123... " .. testy[0])
However this wont:
local myTable = {}
myTable["welcome"] = "1"
I get : attempt to call global 'exportstring' (a nil value)
Expected results - it saves the table.
What happens - it throws the error.

Lua is it possible to "halt" any code execution from within a table?

Something that intrigues me about Lua is the fact that you can run any function from within a table, regardless of whether it returns anything or not, an example of what I am talking about is:
local my_table = {
print("output from a table!");
warn("more output from a table!");
};
The funny thing is that as soon as this table is created both functions inside of it are ran, and both my_table[1] and [2] are equal to nil (because print and warn do not return a value). However is there any way to per-say "halt" both functions from executing whenever the table is created, and possibly even "start" running them later, if a certain condition is met or not?
I would appreciate any help; Thanks
You're not storing functions in a table that way, you're storing results of calls.
If you need functions, create anonymous functions explicitly.
local mytable = {
function() print("output from a table!") end,
function() warn("more output from a table!") end
}
If you don't like this way, there's another. Capture function and arguments in a lexical closure, and apply stored arguments when that closure will be called.
local function delay(func, ...)
local args = {...}
return function()
func(table.unpack(args))
end
end
local mytable = {
delay(print, "output from a table!"),
delay(warn, "more output from a table!")
}
mytable[1]()
mytable[2]()

Passing session between two lua files

I want to call another lua script from my main script say like
session:execute("lua","/path/somefile.lua "..somearg1.." "..somearg2..)
its working fine and somefile.lua is executing but suppose i also want to use session there i.e. i am accessing a database in somefile.lua and want to speak a query result in somefile.lua by using session. (session:speak(queryResult)).
i also tried sending session as one of argument
session:execute("lua","/path/somefile.lua "..session)
but it gives a error "attempt to concatenate global 'session' (a userdata value)"
any advise..??
code of first lua file
session:answer();
session:setAutoHangup(false);
session:set_tts_params("flite","kal");
callerId = session:getVariable("caller_id_number");
session:execute("lua ","/etc/freeswitch/scripts/checkbal.lua "..callerId.." "..session);
session:destroy();
code for 2nd lua file
callerId=argv[1];
session=argv[2];
luasql = require "luasql.postgres";
env=assert(luasql:postgres());
con=assert(env:connect("mydb","postgres","password","127.0.0.1","5432"));
cur=assert(con:execute("select balance from bal where number='"..callerId.."'"));
session:set_tts_params("flite","kal");
row=cur:fetch({},"a");
res=row.balance;
session:speak(res);
Rig your second file to be a module that returns a function or a table of functions. Here is an example that has second file return a "speak" function that you can then re-use as many times as desired:
Code of first Lua file:
session:answer()
session:setAutoHangup(false)
session:set_tts_params("flite","kal")
callerId = session:getVariable("caller_id_number")
speak = require 'checkbal'
speak(session, callerId)
-- session:execute("lua ","/etc/freeswitch/scripts/checkbal.lua "..callerId.." "..session)
session:destroy()
Code for 2nd Lua file:
luasql = require "luasql.postgres"
local env=assert(luasql:postgres())
local con=assert(env:connect("mydb","postgres","password","127.0.0.1","5432"))
local function speak(session, callerId)
local cur = assert(con:execute("select balance from bal where number='"..callerId.."'"))
session:set_tts_params("flite","kal")
row=cur:fetch({},"a")
res=row.balance
session:speak(res)
end
return speak
Note: this is Lua: no need for semicolons.
I would consider making "session" an object (table with methods) with a "speak" method, but this is going beyond scope of this question and is not necessary, may just lead to more maintainable code later.

I need clarification on Metatable.__index

I asked earlier why my methods for a metatable weren't being located by Lua, and was told that by setting __index to my metatable, that it would resolve the issue, so I assumed that a method when called was searching by index in the metatable, but I've ran into an issue now that I need to use indexing brackets [ and ] on my metatable, so __indexis assigned to return an index from a table inside of it, how do I resolve the functionality needs of both using methods, and use of indexing brackets
I wrote a minimal example indicating the problem:
TestMetatable = {DataTable = {}}
TestMetatable.__index = TestMetatable
function TestMetatable.new()
local Tmp = {}
setmetatable(Tmp,TestMetatable)
Tmp.DataTable = {1}
return Tmp
end
function TestMetatable:TestMethod()
print("Ran Successfully")
end
function TestMetatable.__index(self,index)
return self.DataTable[index]
end
local Test = TestMetatable.new()
-- both functionalities are needed
print(Test[1])
Test:TestMethod()
You need to understand the difference between __index and __newindex, and their relationship with the current contents of the main table.
__newindex is only called/accessed when all the following are true:
When you are setting a value into the main table, via tbl[index] = expr (or equivalent syntax, like tbl.name = expr).
When the key you are trying to set into the main table does not already exist in the main table.
The second one trips people up often. And that's your problem here, because __index is only accessed when:
When the key being read from the main table does not already exist in the main table.
So if you want to filter every read from and write to a table, then that table must always be empty. Therefore, those reads and writes need to go into some other table you create for each new object. So your new function needs to create two tables: one that remains empty and one that has all the data in it.
Honestly, I wish Lua had a way to create just an empty piece of userdata that you could bind a user-defined metatable to, just to avoid these issues.
the way I resolved this problem, according to Nicol Bolas's solution, if it might give clarity to anyone else's confusion :-)
TestMetatable = {DataTable = {}, FunctionTable = {}}
function TestMetatable.new()
local Tmp = {}
setmetatable(Tmp,TestMetatable)
Tmp.DataTable = {1}
Tmp.FunctionTable = TestMetatable
return Tmp
end
function TestMetatable:TestMethod()
print("Ran Successfully")
end
function TestMetatable.__index(self,index)
if type(index) == "string" then
return self.FunctionTable[index]
else
return self.DataTable[index]
end
end
local Test = TestMetatable.new()
-- both functionalities are needed
print(Test[1])
Test:TestMethod()

How to load a file data in memory,and don't reload again. just like static field in java?

I have a function :it's load a file data and build a table.
I want to load the file only once , everytime call the function and get return table in memory,don't load file again(you know io operation repeat is bad).
the goal is just like static field in java,only build once , and use it .
how to do ?
You can do this in one of several ways. For example:
local myInternalLocal = nil
function FuncName(...)
if(not myInternalLocal) then
myInternalLocal = --Do stuff that builds the table.
end
return myInternalLocal
end
Alternatively, you can do it by replacement, which better hides the internal variable, and is (very slightly) faster:
function FuncName(...)
local myInternalLocal = --Do stuff that builds the table.
FuncName = function()
return myInternalLocal
end
end
The downside here has to do with modules. If this is inside of a module, then you may need to change how it rebinds the function. And of course, if someone stores the old function before calling it, they can keep calling the original version.
I think you want to use require to load the file.

Resources