Error In Lua - Loop on map/list - lua

I wrote the following function: deleteStrings .
That gets as input map of words and their length (mapWords),
and list of words.(listWords)
I want to remove from the map, keys that don't exist in the list.
I'm getting "lua error".
function deleteStrings(mapWords,listWords)
local CleanedMap = mapWords
for key in map.keys(mapWords) do
if not contains(listWords,key) then
CleanedMap=map.remove(CleanedMap,key)
end
end
end
function contains(list, word)
for _, v in pairs(list) do
if v == word then return true end
end
return false
end
What is wrong with this code?
Thanks

Related

Lua add key value pair into table (array)

In my Lua project I receive an array, encode it into JSON and pass further. My Lua encode function looks like the following:
local function encode_table(val, stack)
local res = {}
stack = stack or {}
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if val[1] ~= nil or next(val) == nil then
-- Treat as array -- check keys are valid and it is not sparse
local n = 0
for k in pairs(val) do
if type(k) ~= "number" then
error("invalid table: mixed or invalid key types")
end
n = n + 1
end
-- need to add a stub somewhere here above the next line
if n ~= #val then
error("invalid table: sparse array") -- THIS TRIGGERS and stops the code
end
-- Encode
for i, v in ipairs(val) do
table.insert(res, encode(v, stack))
end
stack[val] = nil
return "[" .. table.concat(res, ",") .. "]"
else
-- Treat as an object
for k, v in pairs(val) do
if type(k) ~= "string" then
error("invalid table: mixed or invalid key types")
end
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
end
stack[val] = nil
return "{" .. table.concat(res, ",") .. "}"
end
end
The problem is that I reveive an array with a 1 element missing. I need to add a stub for it in a key - value manner, say
myArray['missingKey'] = 'somestubvalue'
but I donk know how to do that. Also there is a check in the code for sparse array and this check throws an error, so I need to add a stub before this check is done (pls see the code). Any ideas how to do that would be welcome. Thank you.

How do I create a function that returns the first non-nil, non-empty string passed to it?

I'm trying to implement a function that returns the first non-blank string from the variables passed to it. Unfortunately, some of these variables might be nil, so the naive approach
function first_non_empty(...)
for i, item in ipairs({...}) do
if item ~= nil and item ~= '' then
return item
end
end
return ''
end
doesn't work: ipairs quits out as soon as it encounters a nil value. This can be fixed by changing the requirements so that the variables can't be nil, or by passing the length to the function so table length doesn't have to rely on ipairs, or by wrapping all parameters in a function so that none of them are explicitly nil
function first_non_empty_func(...)
for i, func in ipairs({...}) do
local item = func()
if item ~= nil and item ~= '' then
return item
end
end
return ''
end
function fn(p)
local f = function() return p end
return f
end
-- change callers to first_non_empty_func(fn(a), fn(b), fn(c))
However, both of these solutions complicate the function prototype. Does there exist a function taking an ordered list of parameters, some of which may be nil, which returns the first of those parameters which is both non-nil and not an empty string?
Use table.pack, which preserves all nil entries and returns the number of entries in the n field:
function first_non_empty_pack(...)
local t = table.pack(...)
for i = 1, t.n do
local item = t[i]
if item ~= nil and item ~= '' then
return item
end
end
return ''
end
select('#', ...) can be used to get the number of provided arguments, so here is an alternative that doesn't use table.pack:
function first_non_empty_pack(...)
for i = 1, select('#', ...) do
local item = select(i, ...)
if item ~= nil and item ~= '' then
return item
end
end
return ''
end
Simpler approach is to use recursion. No extra tables created, etc:
function first_non_empty(item, ...)
if item ~= nil and item ~= '' then return item end
return first_non_empty(...)
end
But the list has to end with some ending marker. For example, boolean 'false', indicating there's no non-nil, nonempty strings.

Lua Set Functions in ComputerCraft

I have a ComputerCraft program set to turn on a siren when any non-whitelisted players are near:
sensor = peripheral.wrap("top")
function arraysubset(a, b)
local s = set(b)
for _, el in pairs(a)
if not s[el] then
return false
end
end
return true
end
function sirenOn() rs.setBundledOutput("back",colors.blue) end
function sirenOff() rs.setBundledOutput("back",0) end
while 1 do
playersNear = sensor.getPlayerNames()
allowedPlayers = {"VirtualDXS","jettrom","Shad0wlurker16","Demonicmobster","FireFang0113","riggs135","DaisySnow123","MasterAlex930"}
if playersNear[1] ~= nil then
if arraysubset(playersNear,allowedPlayers) then sirenOff() else sirenOn() end
else sirenOff() end
end
However, on line 3 I get an attempt to call nil. This makes me think that the set() function is not present on computercraft. I'm wondering:
Is there another (maybe better) way to find if array a is a subset of array b and
If not where can I get an API with the set() function?
Rereading the source for the subset() code, I am seeing that the code I used required more code from earlier in the answer:
function set(list)
local t = {}
for _, item in pairs(list) do
t[item] = true
end
return t
end

How does the __call metamethod in Lua 5.1 actually work?

I'm trying, as an exercise, to make a set implementation in Lua. Specifically I want to take the simplistic set implementation of Pil2 11.5 and grow it up to include the ability to insert values, delete values, etc.
Now the obvious way to do this (and the way that works) is this:
Set = {}
function Set.new(l)
local s = {}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.insert(s, v)
s[v] = true
end
ts = Set.new {1,2,3,4,5}
Set.insert(ts, 5)
Set.insert(ts, 6)
for k in pairs(ts) do
print(k)
end
As expected I get the numbers 1 through 6 printed out. But those calls to Set.insert(s, value) are really rather ugly. I'd much rather be able to call something like ts:insert(value).
My first attempt at a solution to this looked like this:
Set = {}
function Set.new(l)
local s = {
insert = function(t, v)
t[v] = true
end
}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
This works mostly fine until you see what comes out of it:
1
2
3
4
5
6
insert
Very obviously the insert function, which is a member of the set table, is being displayed. Not only is this even uglier than the original Set.insert(s, v) problem, it's also prone to some serious trouble (like what happens if "insert" is a valid key someone is trying to enter?). It's time to hit the books again. What happens if I try this instead?:
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__call = Set.call})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(f)
return Set[f]
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't exist to be called means that the ts metatable is going to be searched for "__call".
The ts metatable's "__call" key returns Set.call.
Now Set.call is called with the name insert which causes it to return the Set.insert function.
Set.insert(ts, 5) is called.
What's really happening is this:
lua: xasm.lua:26: attempt to call method 'insert' (a nil value)
stack traceback:
xasm.lua:26: in main chunk
[C]: ?
And at this point I'm stumped. I have absolutely no idea where to go from here. I hacked around for an hour with varying degrees of increasingly desperate variations on this code but the end result is that I have nothing that works. What undoubtedly obvious thing am I overlooking at this point?
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't exist to be called means that the ts metatable is going to be searched for "__call".
There's your problem. The __call metamethod is consulted when the table itself is called (ie, as a function):
local ts = {}
local mt = {}
function mt.__call(...)
print("Table called!", ...)
end
setmetatable(ts, mt)
ts() --> prints "Table called!"
ts(5) --> prints "Table called!" and 5
ts"String construct-call" --> prints "Table called!" and "String construct-call"
Object-oriented colon-calls in Lua such as this:
ts:insert(5)
are merely syntactic sugar for
ts.insert(ts,5)
which is itself syntactic sugar for
ts["insert"](ts,5)
As such, the action that is being taken on ts is not a call, but an index (the result of ts["insert"] being what is called), which is governed by the __index metamethod.
The __index metamethod can be a table for the simple case where you want indexing to "fall back" to another table (note that it is the value of the __index key in the metatable that gets indexed and not the metatable itself):
local fallback = {example = 5}
local mt = {__index = fallback}
local ts = setmetatable({}, mt)
print(ts.example) --> prints 5
The __index metamethod as a function works similarly to the signature you expected with Set.call, except that it passes the table being indexed before the key:
local ff = {}
local mt = {}
function ff.example(...)
print("Example called!",...)
end
function mt.__index(s,k)
print("Indexing table named:", s.name)
return ff[k]
end
local ts = {name = "Bob"}
setmetatable(ts, mt)
ts.example(5) --> prints "Indexing table named:" and "Bob",
--> then on the next line "Example called!" and 5
For more information on metatables, consult the manual.
You said:
Now the way I'm reading this code is:
When I call ts:insert(5), the fact that insert doesn't
exist to be called means that the ts metatable is going
to be searched for "__call".
The ts metatable's "__call" key returns Set.call.
Now Set.call is called with the name insert which causes
it to return the Set.insert function.
Set.insert(ts, 5) is called.
No, what happens is this:
When insert isn't found directly in the ts object, Lua looks for __index in its metatable.
If it is there and it is a table, Lua will search for insert there.
If it is there and it is a function, it will call it with the original table (ts in this case) and the key being searched for (insert).
If it isn't there, which is the case, it is considered nil.
The error you're having is because you don't have __index set in your metatable, so you are effectively calling a nil value.
This can be solved by pointing __index to some table, namely Set, if you're going to store your methods there.
As for __call, it is used for when you call the object as a function. Ie:
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__index=Set, __call=Set.call})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(s, f)
-- Calls a function for every element in the set
for k in pairs(s) do
f(k)
end
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
ts(print) -- Calls getmetatable(ts).__call(ts, print),
-- which means Set.call(ts, print)
-- The way __call and __index are set,
-- this is equivalent to the line above
ts:call(print)
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__index=Set})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(f)
return Set[f]
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
I modified your first version and this version would offer the features I think you are looking for.
Set = {}
Set.__index = Set
function Set:new(collection)
local o = {}
for _, v in ipairs(collection) do
o[v] = true
end
setmetatable(o, self)
return o
end
function Set:insert(v)
self[v] = true
end
set = Set:new({1,2,3,4,5})
print(set[1]) --> true
print(set[10]) --> nil
set:insert(10)
print(set[10]) --> true

get nested table result in lua

I have a table A that contain the following
for i,v in pairs(Table A) do print (i,v) end
1 a
2 table : 50382A03 -- table B
3 hi
. Is there a way that I can get the table B value to be print out while I m printing the parent table A, or i can store it and print it again using the same function?.
thanks
Jp
When the question contains "nested", the answer will probably contain recursion:
function printTable(t)
function printTableHelper(t, spacing)
for k,v in pairs(t) do
print(spacing..tostring(k), v)
if (type(v) == "table") then
printTableHelper(v, spacing.."\t")
end
end
end
printTableHelper(t, "");
end
Just beware of circular references.
A bit changed function for better output and abstraction:
function printTableHelper(t,spacing)
local spacing = spacing or ''
if type(t)~='table' then
print(spacing..tostring(t))
else
for k,v in pairs(t) do
print(spacing..tostring(k),v)
if type(v)=='table' then
printTableHelper(v,spacing..'\t')
end
end
end
end
printTableHelper({'a',{'b'},'c'})
Just head on to the lua-users wiki page on table serialization and choose your champion. For example the following code handles everything including cycles in tables (local a={}; a.t = a):
-- alt version2, handles cycles, functions, booleans, etc
-- - abuse to http://richard.warburton.it
-- output almost identical to print(table.show(t)) below.
function print_r (t, name, indent)
local tableList = {}
function table_r (t, name, indent, full)
local serial=string.len(full) == 0 and name
or type(name)~="number" and '["'..tostring(name)..'"]' or '['..name..']'
io.write(indent,serial,' = ')
if type(t) == "table" then
if tableList[t] ~= nil then io.write('{}; -- ',tableList[t],' (self reference)\n')
else
tableList[t]=full..serial
if next(t) then -- Table not empty
io.write('{\n')
for key,value in pairs(t) do table_r(value,key,indent..'\t',full..serial) end
io.write(indent,'};\n')
else io.write('{};\n') end
end
else io.write(type(t)~="number" and type(t)~="boolean" and '"'..tostring(t)..'"'
or tostring(t),';\n') end
end
table_r(t,name or '__unnamed__',indent or '','')
end

Resources