Как проверить, содержит ли таблица какой-либо ключ внутри __index? - PullRequest
2 голосов
/ 20 марта 2019

Я хочу оптимизировать функцию Фибоначчи, но с помощью индекса таблицы, и запоминание кажется хорошим методом (итерация такая же хорошая) ... Однако вскоре я столкнулся с проблемой: я не могу решить, находится ли ключ вТаблица.Как я могу это сделать?

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})

1 Ответ

2 голосов
/ 21 марта 2019

Ваш код будет работать нормально в его текущем состоянии.Причиной этого является то, что уже зачеркнутые значения имеют более высокий приоритет, чем метаметод __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 уже рассчитано и кэшировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...