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
Related
I have been using parameters to query node indexes as such (using the rest api in java)-
final QueryResult<Map<String,Object>> result = engine.query("start nd=node:name_index(name={src}) return nd.age as age", MapUtil.map("src", "Susan");
However I haven't been able to get this to work for a collection of nodes/names. I have been trying something along the lines of-
final QueryResult<Map<String,Object>> result = engine.query("start nd=node:name_index(name={src}) return nd.age as age", MapUtil.map("src", Arrays.asList("Susan","Brian", "Ian"));
But it refuses to compile. I as wondering if there is something wrong in my syntax or that parameters are not designed to work in this context.
The name= syntax in the start is meant to do an index lookup on a property. It won't do an IN lookup. The way you can do this sort of lookup is like this (note it depends on Apache's StringUtils):
List<String> names = Arrays.asList("Susan","Brian", "Ian");
String luceneQuery = "name:("+StringUtils.join(names, ",")+")";
engine.query("start nd=node:name_index({luceneQuery}) return nd.age as age", MapUtil.map("luceneQuery", luceneQuery));
Just a note, this is the "legacy" index way of doing things. In 2.0 they've introduced label-based indexes, which work entirely differently.
Thanks a lot; though it would still only return a non empty answer when I added a space after the comma in line 2. I used-
String luceneQuery = "name:("+StringUtils.join(names, ", ")+")";
and it returned the age of one person. When I tried this:
String luceneQuery = "fs:(fs:"+ StringUtils.join(names, " OR fs:")+")";
it gave me all three ages. However, I am still unsure about whether this query will be able to leverage the usual advantages of parameters , i.e. will the engine be able to reuse the query and execution path the next time around (this time we may want to query for 4 names instead of 3)
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.
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.
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).
I've put some code like this
flash[:task_loader] = flash[:task_loader]
flash[:task_loader_params] = flash[:task_loader_params]
in a function in my controller which all my actions can call. This has the effect of keeping those two flash entries in the FlashHash. (I presume this rather odd-looking code works because the '=' does more than just assign values.)
My question is, is there a better way to do this? Something like
flash[:task_loader].pin
Flash is a convenient wrapper for storing data in cookies and expiring them in the next request. So that your notification messages will work through 2 (or multiple) request response cycles.
If you want some more persistence, you can use session:
session[:task_loader] = my_task_loader
Note that one cookie can hold only 4KB of data.
(I presume odd-looking code works
because the '=' does more than just
assign values.)
This is because it is not simply an assignment, but a method []=, with a signature similar to this:
def []=(k, v)