19.1 数组大小

Lua中我们经常假定array在最后一个非nil元素处结束。这个传统的约定有一个弊端:我们的array中不能拥有nil元素。对大部分应用来说这个限制不是什么问题,比如当所有的array有固定的类型的时候。但有些时候我们的array需要拥有nil元素,这种情况下,我们需要一种方法来明确的表明array的大小。

Table库定义了两个函数操纵array的大小:getn,返回array的大小;setn,设置array的大小。如前面我们所见到的,这两个方法和table的一个属性相关:要么我们在table的一个域中保存这个属性,要么我们使用一个独立的(weaktable来关联table和这个属性。两种方法各有利弊,所以table库使用了这两个方法。

通常,调用table.setn(t, n)使得tn在内部(weaktable关联,调用table.getn(t)将得到内部table中和t关联的那个值。然而,如果表t有一个带有数字值n的域,setn将修改这个值,而getn返回这个值。Getn函数还有一个选择:如果他不能使用上述方法返回array的大小,就会使用原始的方法:遍历array直到找到第一个nil元素。因此,你可以在array中一直使用table.getn(t)获得正确的结果。看例子:

print(table.getn{10,2,4})          --> 3

print(table.getn{10,2,nil})        --> 2

print(table.getn{10,2,nil; n=3})   --> 3

print(table.getn{n=1000})          --> 1000

 

a = {}

print(table.getn(a))               --> 0

table.setn(a, 10000)

print(table.getn(a))               --> 10000

 

a = {n=10}

print(table.getn(a))               --> 10

table.setn(a, 10000)

print(table.getn(a))               --> 10000

默认的,setngetn使用内部表存储表的大小。这是最干净的选择,因为它不会使用额外的元素污染array。然而,使用n域的方法也有一些优点。在带有可变参数的函数种,Lua内核使用这种方法设置arg数组的大小,因为内核不依赖于库,他不能使用setn。另外一个好处在于:我们可以在array创建的时候直接初始化他的大小,如我们在上面例子中看到的。

使用setngetn操纵array的大小是个好的习惯,即使你知道大小在域n中。table库中的所有函数(sortconcatinsert等等)都遵循这个习惯。实际上,提供setn用来改变域n的值可能只是为了与旧的lua版本兼容,这个特性可能在将来的版本中改变,为了安全起见,不要假定依赖于这个特性。请一直使用getn获取数组大小,使用setn设置数组大小。


相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛