Ваш код будет работать нормально в его текущем состоянии.Причиной этого является то, что уже зачеркнутые значения имеют более высокий приоритет, чем метаметод __index
, поэтому, если значение существует, оно возвращается немедленно.Существует несколько оптимизаций, которые могут сделать ваш код лучше:
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})
Здесь я вообще убираю объявление функции (если вы хотите использовать его повторно, рассмотрите возможность сделать вашу функцию локальной с local function
вместо function
) и упростили код, добавив начальные значения непосредственно в объявление таблицы (без индекса 0
, чтобы сохранить его в неизменном виде, а также без нуля в результатах) и используя тот факт, что setmetatable
возвращает первоначально переданную таблицу.Вы можете удалить assert
, если хотите, но, вероятно, неплохо бы увидеть осмысленное сообщение об ошибке вместо «переполнения стека».
И если вы действительно хотите проверить, существует ли значение вtable (этот код не требует этого), используйте rawget
:
rawget(fib, 10) == nil
сообщит, что 10
уже рассчитано и кэшировано.