Ответ 1
Цитирование справочника Lua 5.2:
the length of a table t is only defined if the table is a sequence, that is, the set of its positive numeric keys is equal to {1..n}
for some integer n
Результатом оператора #
на непостоянствах является undefined.
Но что происходит в реализации C Lua, когда мы вызываем #
на непоследовательность?
Фон: Таблицы в Lua внутренне разделены на часть массива и хэш-часть. Это оптимизация. Lua пытается избежать выделения памяти часто, поэтому он предварительно выделяет для следующей мощности два. Это еще одна оптимизация.
- Когда последним элементом в массиве является
nil
, результат#
- это длина кратчайшей допустимой последовательности, найденной путем binsearching части массива для первого ключа nil-follow. - Когда последний элемент в массиве не является
nil
И хэш-часть пуста, результатом#
является физическая длина части массива. - Когда последний элемент в массиве не является
nil
И хэш-часть НЕ пуста, результатом#
является длина самой короткой допустимой последовательности, найденной путем бинарного поиска хэш-части для первого nil- (это такое положительное целое числоi
, чтоt[i] ~= nil
иt[i+1] == nil
), считая, что часть массива заполнена не-нильскими (!).
Таким образом, результат #
- это почти всегда (желаемая) длина кратчайшей допустимой последовательности, если последний элемент в массиве, представляющий не-последовательность, не равен нулю. Затем результат больше желаемого.
Почему? Похоже, что еще одна оптимизация (для массивов с мощностью-два). Сложность #
в таких таблицах O(1)
, а другие варианты O(log(n))
.