Вопрос
Я наткнулся на странное поведение в функции распаковки Lua
table1 = {true, nil, true, false, nil, true, nil}
table2 = {true, false, nil, false, nil, true, nil}
a1,b1,c1,d1,e1,f1,g1 = unpack( table1 )
print ("table1:",a1,b1,c1,d1,e1,f1,g1)
a2,b2,c2,d2,e2,f2,g2 = unpack( table2 )
print ("table2:",a2,b2,c2,d2,e2,f2,g2)
Выходной сигнал:
table1: true nil true false nil nil nil
table2: true false nil nil nil nil nil
Вторая распаковка доставляет параметры вплоть до первого нулевого значения.Я мог бы жить с этим.Первая таблица содержит 4?параметры, в середине которых единица равна нулю.У него есть 4 параметра, которые не равны нулю, но они не те, которые показаны.
Кто-нибудь мог бы это объяснить?Это было опробовано с codepad.org и lua 5.1
Решение
Проблема может быть решена простым указанием начального и конечного индексов для unpack()
и используя table.maxn()
в качестве конечного индекса:
table1 = {true, nil, true, false, nil, true, nil} a1,b1,c1,d1,e1,f1,g1 = unpack( table1, 1, table.maxn(table1) ) print ("table1:",a1,b1,c1,d1,e1,f1,g1) -->table1: true nil true false nil true nil
Истинная причина расхождения в том, как обрабатываются две таблицы, кроется в логике определения длины части массива таблицы.
В luaB_unpack()
использование функции luaL_getn()
который определяется в терминах lua_objlen()
который призывает luaH_getn()
для столов.В luaH_getn()
просматривает последнюю позицию массива, и если она равна nil
выполняет бинарный поиск границы в таблице ("такой, что t[i] не равно нулю, а t[i+1] равно нулю").Двоичный поиск в конце массива является причиной того , что table1
тогда обрабатывается по-другому table2
.
Это должно быть проблемой только в том случае, если последняя запись в массиве nil
.
От Программирование на Lua (стр. 16) (Вам следует купить эту книгу.):Когда в массиве есть отверстия - nil элементов внутри него - оператор длины может использовать любой из этих nil элементов в качестве конечного маркера.Поэтому вам следует избегать использования оператора длины в массивах, которые могут содержать пробелы.
В unpack()
использует оператор длины lua_objlen()
, который "может принимать любой из нулевых элементов в качестве конца" массива.
Другие советы
[...] Тип таблица реализует ассоциативные массивы, то есть массивы, которые могут быть проиндексированы не только числами, но любым значением (кроме nil).Таблицы могут быть разнородными;это, они может содержать значения всех типов (кроме nil). [...]
Данный nil
к записи будет перерыв перечисление таблицы и ваши переменные не будут инициализированы должным образом.
Вот простой пример, который демонстрирует проблематичный поведение:
table1 = {true, false, nil, false, nil, true, nil}
for k,v in ipairs(table1) do
print(k, v)
end
выходной сигнал:
1 true
2 false
>Exit code: 0