2009-11-04 13 views
9

I natknął się na dziwne zachowanie w Lua funkcja rozpakowaćLua rozpakować błąd?

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) 

wyjściowa:

table1: true nil true false nil nil nil 
table2: true false nil nil nil nil nil 

Drugi rozpakować dostarcza parametrów do pierwszej wartości zerowej. Mógłbym z tym żyć. Pierwsza tabela zapewnia 4? parametry z jednym zero w środku. Ma 4 parametry, które nie są zerowe, ale nie są tymi, które są pokazane.

Czy ktoś może to wyjaśnić? ten został wypróbowany z codepad.org i Lua 5,1

Odpowiedz

12

Problem może być rozwiązany jedynie poprzez określenie początku i końca indeksy unpack() i korzystania table.maxn() jako indeks końcowy:

 
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 

Prawdziwą przyczyną rozbieżności w sposobie obsługi dwóch tabel jest logika określania długości części tablicy w tabeli.

Funkcja luaB_unpack() wykorzystuje luaL_getn() która jest definiowana w kategoriach lua_objlen() który wzywa luaH_getn() na stołach. luaH_getn() sprawdza ostatnią pozycję tablicy, a jeśli jest to nil wykonuje binarne wyszukiwanie granicy w tabeli ("takie, że t [i] wynosi zero, a t [i + 1] wynosi zero"). Wyszukiwanie binarne końca tablicy jest przyczyną, że table1 jest obsługiwane inaczej niż table2.

To powinno być problemem tylko wtedy, gdy ostatni wpis w tablicy to nil.

Od Programming in Lua (pg.16) (Należy kupić tę książkę.): Kiedy tablica posiada otwory - nil elementów wewnątrz niego - operator długość może założyć każdy z tych elementów jako zerowe znacznika końcowego.Dlatego należy unikać używania operatora długości na tablicach, które mogą zawierać dziury.

Urządzenie unpack() używa operatora długości lua_objlen(), który "może przyjąć dowolny z zerowych elementów jako koniec" tablicy.

+0

Dziękuję, uratowałeś mój dzień. Czy to oznacza, że ​​table.maxn() przemierza cały przydzielony rozmiar dla tabeli? – Geggamojja

+0

table.maxn() "Zwraca największy dodatni indeks numeryczny danej tabeli" zobacz http://www.lua.org/manual/5.1/manual.html#pdf-table.maxn – gwell

+0

jest table.maxn naprawdę gwarantowane zwraca tu poprawną wartość (= liczba obiektów w literale tabeli)? – u0b34a0f6ae

3

2.2 - Values and Types

[...] Typ stół realizuje asocjacyjne tablice, czyli tablice, które mogą być indeksowane nie tylko z liczb, ale o dowolnej wartości (oprócz zera). Tabele mogą być heterogeniczne; to znaczy, mogą one zawierać wartości wszystkich typów (oprócz zera). [...]

Biorąc nil do wpisu będzie przerwa wyliczenie stół i twoi zmienne przyzwyczajenie być właściwie Init.

Oto prosty przykład, który demonstruje problematyczne zachowanie:

table1 = {true, false, nil, false, nil, true, nil} 
for k,v in ipairs(table1) do 
    print(k, v) 
end 

wyjściowa:

1 true 
2 false 
>Exit code: 0 
+0

Dokładniej, podejrzewam, że ignoruje 'nil's on określony. – RCIX

+0

Nie, nie RCIX, w takim przypadku tabela 2 również zwróciłaby 4 wartości. – Geggamojja

+0

Jedynym powodem zatrzymania pętli for jest to, że iterator zwrócił zero w pozycji 3. Tabela była nadal poprawnie zainicjowana, ponieważ 'assert (table1 [1] == true i table1 [2] == false i table1 [3] == zero i table1 [4] == false i table1 [5] == zero i table1 [6] == true i table1 [7] == zero) 'does not assert. – gwell