Luaテーブル長さ

1327 ワード

疎配列の長さが返されるのは間違っていて、バグかどうか分かりません.(Lua 5.2.2でテストした)テーブル容量の半分の要素を'#'で長さを取るのが間違っている場合.しかし、容量の半分未満の場合、表現は正しい.Luaのコード実装によれば,‘#’号はテーブル長をとるときにテーブルの最初の空要素の前の位置を取得する.原文は(luaH_getn注釈):Try to find a boundary in table`t'.A `boundary' is an integer index such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).例を見てみましょう.
a = {}
for i = 1, 2 do
    a[i] = i*3
end
a[4] = 811

#aで取得した結果は4であり、上記の説明に従って2を取り戻すべきである.次のようになります.
for i = 1, 4 do
    a[i] = i*3
end
a[8] = 811

#aで取得した結果は8であり、上記の説明に従って4を取り戻すべきである.古いバージョンではtableが使えます.maxnは最大の下付きを取り、新バージョンではこのインタフェースが廃止された.簡単な解析では,テーブル内の要素が少なく,インデックスのスパンが大きい場合,すなわち疎な配列に対して格納される場合にテーブルのハッシュ部分が存在するためである.しかし、配列がそれほどまばらではない場合、配列部分は存在し、下付きで1からインクリメントされる.これも空間使用の最適化です.長さを取る実装を見てみましょう(分析に役立つ部分だけを切り取ります)
unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
  // some codes
}
/* else must find a boundary in hash part */
else if (isdummy(t->node)) /* hash part is empty? */
  return j; /* that is easy... */
//some other codes

ifの後ろのテーブルの最後の要素が空になっていることに注意してください.この場合、上の2つのコードa[4]またはa[8]に対して、ちょうど配列の最後の要素に位置しているので、空ではありません.ifの中では実行されません.ここのテーブルにはハッシュ部分がないので,else ifに直接テーブル長,すなわち上に見た4または8を返す.しかし、実際には、この操作には意味がないので、疎配列については'#'で長さを取らないでください.