Почему не проходит проверка нуля

Я использую Lua для запроса Redis и хочу проверить, нет ли ключа, но не понимаю, почему мой код не работает:

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

однако следующий код работает:

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

Что здесь происходит?

Создание Twitter-подобного приложения Trending Topics App с Redis (на примере PHP)
Создание Twitter-подобного приложения Trending Topics App с Redis (на примере PHP)
Redis - это популярная база данных типа "ключ-значение" в памяти с поддержкой различных типов и структур данных, которая в основном используется для...
2
0
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы используете ipairs для перебора таблицы. Итерация закончится на первом элементе nil. Следовательно, v никогда не может равняться нулю внутри вашего цикла for. Таким образом, вы никогда не войдете в оператор if (v== nil).

Из справочного руководства Lua 6.1 Основные функции:

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.

На самом деле вы не можете использовать какие-либо стандартные итераторы для поиска нулевых значений.

Если вы хотите только проверить, является ли bulk[1]nil:

Заменять

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

с участием

local bulk = redis.call("HMGET", KEYS[1], "p1", "p2")
if not bulk[1] then return end

return и return nil кстати одно и то же.

В случае, если bulk[1] может быть действительно false, проверьте явно против nil.

if bulk[1] == nil then return end

Этот код:

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

работает, потому что bulk[1] — это либо 0, либо false, и в этом случае вы заменяете его на 0.

Быстрое исследование подтверждает, что вы получаете ложные значения вместо nil из привязок Redis Lua. Так что использование ipairs должно быть в порядке. Вы должны просто проверить, равно ли значение false, а не nil.

@Джеймс, в следующий раз просто print(bulk[1]) и ты сразу узнаешь, что это false

Piglet 09.04.2019 15:20

Другие вопросы по теме