Lua table.foreach missing - foreach

I used https://www.lua.org/cgi-bin/demo quite a lot to quickly hack together some scripts and test if they actually work. But today I stumpled across something that is very strange.
Testing this code
local t = {}
local threshold = 3
local counter = 0
t["1"] = true
t["2"] = true
t["3"] = false
t["4"] = true
table.foreach(t, print)
table.foreach(
t,
function(k,v)
if v then
counter = counter + 1
end
end
)
print(counter)
gave me this error message
input:9: attempt to call a nil value (field 'foreach')
so I tried running
for k,v in pairs(table) do
print(k,v)
end
resulting in this output
concat function: 0x42be90
remove function: 0x42bca0
sort function: 0x42ba50
move function: 0x42baf0
insert function: 0x42bda0
unpack function: 0x42b2a0
pack function: 0x42b3a0
Since it's about a year ago I last used this site to test my code I can't really tell when there was a change. Or if there was a change. I am very sure last time I used that site I used the table.foreach function. But now it does not work.
I also checked the changelog in case there was a change I missed but https://www.lua.org/versions.html does not show any change past June 2020 with version 5.4
May someone tell me where I messed up or what I am missing?

The error 'attempt to call a nil value (field 'foreach')' is indicating that the table.foreach() function is not defined. This error is likely caused by the fact that the table.foreach() function was removed in Lua 5.3.
In Lua 5.3, the equivalent method for iterating over a table is the pairs() function.
To fix this error you can replace the table.foreach with for k, v in pairs(t) do and replace the second table.foreach with for k, v in pairs(t) do
for k, v in pairs(t) do
print(k,v)
end
counter = 0
for k, v in pairs(t) do
if v then
counter = counter + 1
end
end
print(counter)

Related

How to check if a table contains some key inside __index?

I want to optimize a Fibonacci function but using table index, and memoization seems a good method (iteration is as good)... However, soon I ran into a problem: I can't decide whether a key is in a table. How can I do that?
local fib = {}
function fib_index(t, k)
if k == 0 or k == 1 then
t[k] = k
else
t[k] = t[k-1] + t[k-2]
end
return t[k]
end
setmetatable(fib, {__index = fib_index})
Your code will run just fine in it's current state. The reason behind that is that already strored values have highter priority than __index metamethod, so if value does exist, it's returned immideately. There are few optimisations which can make your code look better:
local fib = setmetatable({1, 1}, {__index = function(t,k)
assert(k > 0, 'Invalid fib index') -- Most basic check
local res = t[k-1] + t[k-2]
t[k] = res
return res
end})
Here I remove function declaration at all (if you want to reuse it, consider making your function local with local function instead of function) and made code easier by adding inital values directly into table declaration (no index 0 to keep it lua way, also no zero in results) and utilizing the fact that setmetatable return originally passed table. You can remove assert if you want to, but it's probably good idea to see meaningful error message instead of "stack overflow".
And if you really wanna check does value exist in table (this code does not require this), use rawget:
rawget(fib, 10) == nil
will tell you is 10 already calculated and cached.

LUA: trying to remove a value from a table when it is found in another table

I'm trying to delete a key and value from a table when it is found in another table. I've been using this so far but although it recognizes the duplicate, it always removes the last item in the table...
function get_key_for_value( t, value )
for k,v in pairs(t) do
if v==value then return k
end
return nil
end
end
for k,v in pairs (Iranian_Protected_Groups) do
v[6] = 0
if Springfield_3_Target_Name == v[2] then
v[6] = v[6] + 1
if v[6] > 0 then
local Key_To_Remove = get_key_for_value (Iranian_Protected_Groups, v)
MESSAGE:New( "Shared target is "..v[2], 40):ToBlue()
table.remove (Iranian_Protected_Groups, Key_To_Remove)
end
end
end
any help would be appreciated!
First, you should format your code using standard indentation to make it easier to parse as a human reading the code:
function get_key_for_value(t, value)
for k, v in pairs(t) do
if v == value then
return k
end
return nil
end
end
Look carefully at the for loop. You will never get past the first iteration, because every iteration returns.
Your function is fixed if you move your return nil statement outside the loop. (Though for most purposes, is redundant, because generally no value is equivalent to returning nil).
Before, Key_To_Remove was nil. When passing nil as the index to remove in table.remove, Lua removes the last element. This is convenient when treating a list like a stack, but hid a bug for you in this case.

Perplexing issue with simple coroutine in Lua

I'm learning Lua and trying to create a simple coroutine. In Lua 5.1, the code below gives the error: "attempt to yield across metamethod/C-call boundary." I've read about that limitation and I can't see how it applies to my code. I tried it in Lua 5.2 and got "attempt to yield from outside a coroutine," which is equally confusing to me. I'm sure the answer will be embarrassingly obvious!
output = {}
done = false
function mainLoop()
while not done do
if co == nil then
co = coroutine.create(subLoop())
elseif coroutine.status(co) == "suspended" then
print(output[k])
coroutine.resume(co)
elseif coroutine.status(co) == "dead" then
done = true
end
end
end
function subLoop()
for k=1, 20 do
table.insert(output, "This is line " .. k .. " of the test output")
coroutine.yield()
end
end
mainLoop()
You are calling subLoop
if co == nil then
co = coroutine.create(subLoop())
instead of passing it to coroutine.create
if co == nil then
co = coroutine.create(subLoop)
This results in you attempting to yield from the main state / (not-really-)coroutine, which gives errors with varying descriptions across versions.

Call stack has exceeded maximum of depth of 100 ,Lua

function findWord(s,i)
-- find first word in given text
local j = i+1
while not _isWhite(s:byte(j)) and j < #s do -- getting error here
j = j + 1
end
return s:sub(i,j), j
end
function splitText(s,maxLen)
-- split text into chunks of maxLen length
rs ={}
local function _g(s,i,c,rs)
-- recursively split text
local function _f(s,i,c)
-- recursively find words and add each word to a chunk
local w,i = findWord(s,i)
if i == #s then return c..w end
if #(c..w) <= maxLen then
c = c..w
s = s:sub(i+1,#s,true)
return _f(s,1,c)
else
return c
end
end
rs[#rs+1] = _f(s,1,'')
i = i+#rs[#rs]
if i < #s then
local s = s:sub(i,#s,true)
return _g(s,1,'',rs)
else
return rs
end
end
return _g(s,1,'',rs)
end
I have above function to split a string, It has been working earlier but this time it started giving error "call stack has exceeded maximum of depth of 100, verify a function is not calling itself by accident."
Any idea why I might be getting this error, this behaviour seems random since I am quite sure about rest of the script and same split function has been working fine as well.
EDIT:
Yes, isWhiteSpace was provided to me and has the following code, I am not supposed to change it since it worked earlier . Here is isWhite function:
function _isWhite(byte)
return byte == 32 or byte == 9
end
So both _g and _f call themselves, and _g calls _f. So clearly the recursion-stop conditions you have are too weak. In _g I see
if i < #s then
local s = ...
return _g(s,1,'',rs)
else
return rs
end
which will stop when i >= #s. If this never happens, you will get infinite recursion. It is hard to say by looking at the code how i varies, but based on this line:
i = i+#rs[#rs]
it appears to by some value, but can't say if there is guarantee that stop condition will ever be reached. With _f it is worse: the stop recursion conditions are
if i == #s then return c..w end
and
#(c..w) > maxLen
Again very hard to say if this is strong enough: what if i is greater than #s, does the rest of the function work? Although findWord() returns i<#s for non empty s, not sure what will happen if s empty.
Best way to find out is to put some print statements that give you a trace of _g and _f and the parameters received, this will tell you clearly what stop conditions are being missed.

Pause iteration

I have Lua table, t, which I iterate:
for k, v in pairs(t) do
b = false
my_func(v)
end
and want iteration to pause until b global variable changes to true
Is it possible is Lua?
Unless you're in a coroutine, there's no concept of a Lua variable changing value without your code doing it. So you would be pausing until something that can't possibly happen happens. Lua is inherently single-threaded.
As previously stated, you can use a coroutine to do this, but you'll have to modify your code accordingly:
function CoIterateTable(t)
for k, v in pairs(t) do
b = false
my_func(v)
while(b == false) do coroutine.yield() end
end
end
local co = coroutine.create(CoIterateTable)
assert(co.resume(t))
--Coroutine has exited. Possibly through a yield, possibly returned.
while(co.running()) do
--your processing between iterations.
assert(co.resume(t))
end
Note that changing the table referenced by t between iterations is not going to do something useful.

Resources