Reputation: 9278
I am using Lua to query redis and want to check if a key isn't present but am confused as to why my code isn't working:
local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
if (i == 1) then
if (v == nil) then
return nil -- This is never entered
end
end
end
however the following code does work:
local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
if (i == 1) then
v = v or 0
if (v == 0) then
return nil -- This does work
end
end
end
What is going on here?
Upvotes: 2
Views: 456
Reputation: 28940
You're using ipairs
to iterate over your table. The iteration will end at the first element that is nil
. Hence v
can never equal nil inside your for loop.
So you'll never enter the if (v== nil)
statement.
From the Lua Reference Manual 6.1 Basic Functions:
ipairs (t) Returns three values (an iterator function, the table t, and 0) so that the construction
for i,v in ipairs(t) do body end
will iterate over the key–value pairs (1,t[1]), (2,t[2]), ..., up to the first nil value.
Actually you cannot use any of the standard iterators to find nil values.
If you only want to check if bulk[1]
is nil
:
Replace
local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
if (i == 1) then
if (v == nil) then
return nil -- This is never entered
end
end
end
with
local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
if not bulk[1] then return end
return
and return nil
are the same btw.
In case bulk[1]
may be validly false
check vs nil
explicitly.
if bulk[1] == nil then return end
This code:
local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
for i, v in ipairs(bulk) do
if (i == 1) then
v = v or 0
if (v == 0) then
return nil -- This does work
end
end
end
works because bulk[1]
is either 0
or false
in which case you replace it with 0
.
A quick resarch confirms that you get false values instead of nil from the Redis Lua bindings. So using ipairs
should be fine. You should just check if the value equals false
, not nil
.
Upvotes: 4