Multivalue table in lua - lua

I'm doing some parallel operations in lua. one thread for receiving, one for processing and one for sending again. To pass the data between threads i have been using tables.
Sadly, now i need to pass more than one variable. How do i create a "Multivalue table" ( a table where i can have multiple values per key) without it impacting performance too much, and is there a more efficient way than using tables?
Simplified code so far:
sendQueue = {}
processQueue = {}
function recieveLoop()
while true do
Wait For recieve
table.insert(processQueue, recievedText)
end
end
function processLoop(sender, text, raw)
while true do
for key,value in pairs(processQueue) do
processData
table.insert(recieveQueue, raw)
end
end
end
And then the same for receiveLoop
all of these 3 functions are threaded and run independently of each other.

Tables can hold other tables, so you can store as many variables as you need in each message.
Instead of:
table.insert(queue, datum1)
You can have:
local message = {datum1, datum2}
table.insert(queue, message)
Or simply:
table.insert(queue, {datum1, datum2})
Including as many "parts" to the message as you want. On the receiving end, you can refer to the message parts by index:
print('foo:', message[1], 'bar:', message[2])
Or unpack the elements:
local foo, bar = unpack(message) -- this is `table.unpack` in Lua 5.2
print('foo:', foo, 'bar:', bar)
Or you could use named fields in the message:
local message = {
foo = datam1,
bar = datum2,
}
table.insert(queue, message)
So on and so forth.

Lua's only real type for data structure is table, so you really have no choice, without using userdata (C). However, tables can be keys or values of tables. That is, nesting. That's how you get multiple values.

Related

Lua variable variables

I'm very new to Lua, I'm working with it on an io controller which has strict limits on script sizes so I need to work within these limits.
I have a number of relays which I am controlling (1-64). I need to switch off a relay when an event happens, but the relay I'm switching off can change.
I have a variable that holds the relay number and I need to turn off this relay.
I can achieve this using I statements:
if variable = 1 then
io.relay1=0 //Turns off the relay
end
else if variable = 2 then
io.relay2=0 //Turns off the relay
end
However, this will very quickly become a large script when repeated for the 64 relays. Is it possible to address the relay using the value of the variable as the relay name? Similar to the below:
io.relay{variable}=0 //Turns off the relay1/2/3/4/5 etc. depending on the value of variable
Alternatively, is there another way to keep the code compact?
Use
io["relay".. variable]=0
However, this creates a string every time.
If you can change how io works, a better solution would be to make io.relay a table and then simply do io.relay[variable]=0.
To avoid the string allocation issue that lhf's answer has, you could pre-generate a string table and index into that:
relay_names = {}
for k = 1,64 do
relay_names[k] = "relay"..tostring(k)
end
Then setting the IO states would look something like this:
io[relay_names[1]] = 1

Aerospike - Query with Multiple Filter parameters

I'm trying to query aerospike using multiple filters taking reference from this link.
I am able to query aerospike based on the given lua script for 1 filter parameter but stuck up with lua script when have to pass more than 2 filter parameters (for example passing two more parameters like age, gender with password).
This is my first time with lua.
Lua Script:
local function map_profile(record)
return map {name=record.name, password=record.password}
end
function check_password(stream,password)
local function filter_password(record)
return record.password == password
end
return stream : filter(filter_password) : map(map_profile)
end
Thanks in advance.
The filter function can have extra parameters and return a closure which can both access those, while still conforming to the expected stub of one parameter being the record, with a boolean return value.
local function filter_password(password)
return function(rec)
if rec['password'] and (type(rec['password']) == 'string') and
rec['password'] == password then
return true
end
return false
end
end
local function map_profile(record)
return map {name=record.name, password=record.password}
end
function check_password(stream,password)
return stream : filter(filter_password(password)) : map(map_profile)
end
However, the best way to query or scan for multiple filters these days (ever since release 3.12) is to use predicate filtering. In the majority of cases (unless you need to compare the values of two of the record's bins to each other in some way) you would skip UDFs and use the PredExp class (in the Java client, or its equivalent in another). You'd get back only those records that matched the filter, regardless of how complex of an expression you built. See the examples in the Aerospike Java client, or the C, C# and Go clients.
We developed SQL wrapper for Aerospike, that builds LUA code from your SQL query. It might be helpful to you.

Creating a table with a string name

I've created a lot of string variable names and I would like to use the names as table names ie:
sName1 = "test"
sName2 = "test2"
tsName1 ={} -- would like this to be ttest ={}
tsName2 ={} -- ttest2 = {}
I can't figure out how to get this to work, have gone through various combinations of [] and .'s but on running I always get an indexing error, any help would be appreciated.
In addition to using _G, as Mike suggested, you can simply put all of these tables in another table:
tables = { }
tables[sName1] = { }
While _G works the same way pretty much every table does, polluting global "namespace" isn't much useful except for rare cases, and you'll be much better off with a regular table.
your question is sort of vague, but i'm assuming you want to make tables that are named based off of string variables. one way would be to dynamically create them as global objects like this:
local sName1 = "test"
-- this creates a name for the new table, and creates it as a global object
local tblName = "t".. sName1
_G[tblName] = {}
-- get a reference to the table and put something in it.
local ttest = _G[tblName]
table.insert(ttest, "asdf")
-- this just shows that you can modify the global object using just the reference
print(_G[tblName][1])

Way to deep traverse a Groovy object with dot in string using GPath

The situation I have is that I'm querying MongoDB with a string for a field that is more than one level deep in the object hierarchy. This query must be a string. So for example I'm querying for something like this in Groovy:
def queryField = 'a.b.c' //this is variable and can be different every time
def result = mongodb.collection.findOne([queryField:5])
The problem no arises that in the result I want to find the value of the nested field. With GPath I could go one level deep and get a's value doing this
def aObj = result."a" //or result["a"]
However I want to go deeper than that by doing something like this:
def queryField = "a.b.c" //this can change every time and is not always 'a.b.c'
def cObj = result[queryField] //since field is variable, can't just assume result.a.b.c
This does not work in Groovy right now. There is a bug logged here, but I was wondering if there is a better work around to use for this scenario that is a bit cleaner than me parsing the string by splitting on the dot and then building the object traversal. Note that "a.b.c" is variable and unknown at runtime (e.g. it could be "a.b.d").
Based on the bug/thread it would appear there are some ambiguity problems with supporting a dotted property accessor. Based on the mailing list thread it would seem that evaluating the queryField string would be your best bet:
def result = [a: [b: [c: 42]]]
def queryString = 'a.b.c'
def evalResult = Eval.x(result, 'x.' + queryString)
assert evalResult == 42
Script on Groovy Web Console
The mailing list thread is a little old, so there's a new-ish (since at least 1.7.2) Eval class that can help out with running small snippets that don't have a large binding.
Otherwise, you can split the string and recursively do property evaluations on the object, effectively reproducing a subset of GPath traversal behavior.

Can Lua support case-insensitive method calls?

I'm using Lua as a data description language for my C++ app. I have a bunch of C++ classes bound to Lua using SLB 2.0. I have methods bound such as 'SetPos' or 'SetName'. I specify the position or name (for example) using a table with values keyed as 'pos' or 'name'. I want to be able to take the key, prepend 'set', and call the method, if it exists (it may not). Is that possible? If so, any suggestions?
I know I could make my bound methods lower case, but I'd rather keep them the same as the methods they're bound to (that may be my fallback though). I could try to build the method name based on my naming standards, but case insensitivity is less error prone.
I feel there should be a tricky piece of Lua that could solve this using metatables, but I haven't been able to work it out myself.
Any suggestions?
Thanks!
Case insensitivity is not really something Lua handles. All table lookups and local variable accesses are ultimately case sensitive string compares.
The best solution would be to just accept that you're dealing with a case sensitive system, just like C++, and deal with it.
However, if you really want to, you can do this. The simplest way would be to put every possible case permutation of a name in your function table. So your function table would have this:
["setname"] = theFunction,
["Setname"] = theFunction,
["sEtname"] = theFunction,
["SEtname"] = theFunction,
...
You can of course automate this with a function that takes each name in the table and replicates its data based on the case permutations.
A more involved but easier to use mechanism would be to use the __index and __newindex metamethods along with the empty table trick.
function CreateCaseInsensitiveTable()
local metatbl = {}
function metatbl.__index(table, key)
if(type(key) == "string") then
key = key:lower()
end
return rawget(table, key)
end
function metatbl.__newindex(table, key, value)
if(type(key) == "string") then
key = key:lower()
end
rawset(table, key, value)
end
local ret = {}
setmetatable(ret, metatbl)
return ret
end
Instead of creating a table with {}, you create the table with this function call. The table should otherwise function as normal (though obviously member access will be slightly slower).

Resources