Вопрос

Я наткнулся на странное поведение в функции распаковки 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(), который "может принимать любой из нулевых элементов в качестве конца" массива.

Другие советы

2.2 - Значения и типы

[...] Тип таблица реализует ассоциативные массивы, то есть массивы, которые могут быть проиндексированы не только числами, но любым значением (кроме 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top