luaの怪しげな
luaの#はtableの秩序化シーケンスを取得する個数である.例:
tableの実装では、要素、配列、hashハッシュの2つの方法で要素を保存します.tableの配列要素の個数を取得します.たとえば、上のコードは配列を取得する個数です.ここで、a=1はハッシュ・リストに保存されます.tableにnilをいくつ増やしたら、何か問題がありますか?
local t = {a = 1, 1,3,4,5,6}
print(#t)--5
tableの実装では、要素、配列、hashハッシュの2つの方法で要素を保存します.tableの配列要素の個数を取得します.たとえば、上のコードは配列を取得する個数です.ここで、a=1はハッシュ・リストに保存されます.tableにnilをいくつ増やしたら、何か問題がありますか?
local t = {a = 1, 1,3,nil,4,5,6,nil}
print(#t)--2
はかなり怪しいのではないでしょうか.どうしてこんなことになったの?私たちはソースコードから一歩一歩霧を剥がした.const TValue *luaH_getint (Table *t, lua_Integer key) {
/* (1 <= key && key <= t->sizearray) */
if (l_castS2U(key) - 1 < t->sizearray)
return &t->array[key - 1];
else {
Node *n = hashint(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
return gval(n); /* that's it */
else {
int nx = gnext(n);
if (nx == 0) break;
n += nx;
}
}
return luaO_nilobject;
}
}
static int unbound_search (Table *t, unsigned int j) {
unsigned int i = j; /* i is zero or a present index */
j++;
/* find 'i' and 'j' such that i is present and j is not */
while (!ttisnil(luaH_getint(t, j))) {// nil,
i = j;
if (j > cast(unsigned int, MAX_INT)/2) { /* , j > MAX_INT/2 。 table table */
/* table was built with bad purposes: resort to linear search */
i = 1;
while (!ttisnil(luaH_getint(t, i))) i++;// nil, 。
return i - 1;
}
j *= 2;
}
/* 。 while ,i = j, j = 2 。m = (i + j)/2 m = (j + 2j)/2, ,m = j + floor(j/2), m > j( table ),ttisnil nil,j = m. , i= j , m = (j + floor(j/2) + j)/2 m = j + floor(j/4), table ,ttisnil nil,j = m。 ,m */
while (j - i > 1) {
unsigned int m = (i+j)/2;
if (ttisnil(luaH_getint(t, m))) j = m;
else i = m;
}
return i;
}
int luaH_getn (Table *t) {
unsigned int j = t->sizearray;// table
if (j > 0 && ttisnil(&t->array[j - 1])) {// 0 nil, 。* lua 。
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
while (j - i > 1) {
unsigned int m = (i+j)/2;//
if (ttisnil(&t->array[m - 1])) j = m;
else i = m;
}
return i;
}
/* else must find a boundary in hash part */
else if (isdummy(t->node)) /* hash , */
return j; /* that is easy... */
else return unbound_search(t, j);/* */
}
:
, table nil , m, m-1 nil 。