Redis Lua скрипт не работает как ожидалось


В качестве практического упражнения я пишу lua-скрипт для Redis, который в основном выполняет метод JavaScriptArray#copyWithin () .

Цитирую из MDN,

Метод copyWithin() копирует последовательность элементов массива внутри массив на позицию, начиная с цели. Копия взята из индексные позиции второго и третьего аргументов начинаются и заканчиваются.

Вот сценарий, который я написал до сих пор :

local list = redis.call('lrange', KEYS[1], 0, -1)
local target = tonumber(ARGV[1])
local startIndex = tonumber(ARGV[2])
local len = #list
local endIndex = len

--Handle negative startIndex
if startIndex < 0 then
    startIndex = len+startIndex
end

--If the third argument is provided, get the endIndex from it
if #ARGV > 2 then
    local arg = tonumber(ARGV[3])
    if arg >= 0 then
        if arg < endIndex then
            endIndex = arg
        end
    else
        if len+arg >= 0 then
            endIndex = len+arg
        else
            endIndex = 0
        end
    end
end

--An array containing the elements which will be copied
local targeted_elements = {}

--Fill elements from the list
for i=1, (endIndex-startIndex+1) do
    targeted_elements[i] = list[startIndex+i]
end

--Make sure no additional elements are pushed to the end of array in case of range overflow
local target_end = #targeted_elements

if target + target_end > len then
    target_end = len-target
end

--replace all the changed elements of the list in redis
for i=1, target_end do
    redis.call('lset', KEYS[1], target+(i-1), targeted_elements[i])
end

Во время тестирования первый тестовый случай успешно очищается:

Тестовый случай: convert [1, 2, 3, 4, 5] в [4, 5, 3, 4, 5] используя copyWithin(0, 3)

LRANGE MyList 0 -1
> [1, 2, 3, 4, 5]

EVALSHA "sha1 of script" 1 MyList 0 3
(basically the same as `[1, 2, 3, 4, 5].copyWithin(0, 3)`)
> nil

LRANGE MyList 0 -1
> [4, 5, 3, 4, 5]

Второй тестовый случай, однако, не идут так гладко.

Тестовый случай: convert [1, 2, 3, 4, 5] в [4, 2, 3, 4, 5] используя copyWithin(0, 3, 4)

LRANGE MyList 0 -1
> [1, 2, 3, 4, 5]

EVALSHA "sha1 of script" 1 MyList 0 3 4
(basically the same as `[1, 2, 3, 4, 5].copyWithin(0, 3, 4)`)
> nil

LRANGE MyList 0 -1
> [4, 5, 3, 4, 5]
После некоторой отладки я обнаружил, что значение targeted_elements равно {4, 5} в обоих случаях, тогда как в случае 2 оно должно быть {4}. Есть ли что-нибудь подозрительное в петлях? Любая помощь была бы очень кстати.
1 2

1 ответ:

Я исправил это, изменив следующую часть скрипта:

--Fill elements from the list
for i=1, (endIndex-startIndex+1) do
    targeted_elements[i] = list[startIndex+i]
end

Изменил его на этот:

--Fill elements from the list
    for i=1, (endIndex-startIndex) do
        targeted_elements[i] = list[startIndex+i]
    end

Выражение +1 в выражении for добавило дополнительный элемент в массив. Это сработало в первом случае, потому что выбранная часть была из 3, 5, поэтому 5-3+1 = 3, что означает, что элементы 3 должны быть выбраны. Но так как остались только элементы 2, случай все еще работает.

Тогда как для второго случая, 4-3+1 = 2, что означает 2 элементы были выбраны, вместо 1.