为啥我的 LUA 解释器不能处理字符串键值?

Posted

技术标签:

【中文标题】为啥我的 LUA 解释器不能处理字符串键值?【英文标题】:Why isn't my LUA interpreter able to handle string key values?为什么我的 LUA 解释器不能处理字符串键值? 【发布时间】:2019-07-26 18:46:22 【问题描述】:

同时使用预定义脚本和 LUA 运行时环境测试代码时,LUA 不会采用任何形式的字符串键值。但是,如果使用数值键,LUA 将按预期使用它。当我使用带有 LUA 文件的 Tshark 来解析数据包捕获时,此规则的例外情况。这允许字符串键值语法正常工作。有什么我可能做错了吗?

我尝试过创建多个不同变体的 .lua 脚本文件,包括:

testArray.NewItem = "value1" testArray["NewItem"] = "value1"

NewItemValue = "新项目" testArray[NewItemValue] = "value1"

这些都会导致 nil 值或由于尝试调用 nil 值而导致的错误,具体取决于用于检查的返回样式。

> tcpstream = 
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
> tcpstream[1] = "nothing"
> print(#tcpstream)
1
> print(tcpstream[1])
nothing

在 tcpstream[stream1] = "nothing" 之后的 print(#tcpstream) 的输出应该显示 1 而不是零。随后的 print(tcpstream[1]) 也应该显示“nothing”。

【问题讨论】:

您的测试无效,因此您的结论无效。 print(tcpstream[stream1]) 打印“无”。 【参考方案1】:

来自http://lua-users.org/wiki/TablesTutorial

# 运算符不计算表中的所有项目 (!)。相反,它会找到最后一个整数(非小数)键。由于它的实现方式,如果表中的所有整数键都不连续,则其结果是不确定的。这就是为什么它不应该用于用作稀疏数组的表[2])。

“#”不是计算 Lua 表中元素数量的好方法(有时不正确)。

至于

> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil

Lua 使用键值对,而不是显式索引。如果你做'arr[1] = 22',这意味着键'1'的值是22,而不是第一个元素的值是22。

【讨论】:

您的参考对于撰写本文时的 Lua 版本是正确的。当前版本的参考手册给出了不同的描述。显然,应该使用开始使用版本的参考手册。如果# 用在它设计的表上,那是好的和正确的。【参考方案2】:

长度操作符(#)不像你想象的那样工作,这是 Lua 初学者的常见错误。

#sometable 的默认行为是返回从数字 1(或 5.3 的任何 nil 值之后)开始的连续键的数量。字符串键永远不会使用表的默认 # 运算符进行评估。

在 5.3 中,如果您的序列包含多个 nil 值,则 # 的行为是不确定的。

Lua 5.3 Reference Manual: 3.4.7 – The Length Operator

Lua 5.1 Reference Manual: 2.5.5 – The Length Operator

我将包含 5.1 中的行,因为我觉得它很好地涵盖了有关运算符和表格的信息。虽然注意与 5.3 的工作方式相同,但可能更容易理解为什么您会看到您所做的行为。

2.5.5 – 长度运算符 长度运算符由一元运算符# 表示。字符串的长度是它的字节数(即每个字符为一个字节时字符串长度的通常含义)。

表 t 的长度被定义为任意整数索引 n,使得 t[n] 不为 nil 且 t[n+1] 为 nil;此外,如果 t1 为零,则 n 可以为零。 对于一个从 1 到给定 n 的非 nil 值的常规数组,它的长度正好是 n,它的最后一个值的索引。 如果数组有“洞”(即 nil其他非 nil 值之间的值),那么 #t 可以是直接在 nil 值之前的任何索引(也就是说,它可以将任何这样的 nil 值视为数组的末尾)。

以下是不同表格的一些示例及其# 结果:

table1 =  --number keys in array
  true,
  true,
  true,

table2 =  -- number keys in hash
  [1] = true,
  [2] = true,
  [3] = true,

table3 =  -- only strings as key
  ['1'] = true,
  ['2'] = true,
  ['3'] = true,

table4 =  -- No key 2 defined
  [1] = true,
  -- [2] = true, 
  [3] = true,

table5 =  -- table with both string and number keys
  [1] = true,
  ['2'] = true,

print(#table1) -- 3
print(#table2) -- 3
print(#table3) -- 0
print(#table4) -- v5.3(1 or 3) v5.1(1)
print(#table5) -- 1

【讨论】:

“从数字 1 开始的连续键的数量”:这与您引用的 5.1 参考相矛盾。 @TomBlodget 我已将支持我的主张的手册中的声明加粗。如果该行没有消除矛盾,我可能需要更多信息来理解您所指的矛盾。 #"one", "two", "three", nil, "five", nil, "seven" 根据您的描述,这将是 3。根据 5.1,它可以是任何整数 >= 0。根据 5.3,它可以是 3、5 或 7。简而言之,# 是误用在这样的表上。 @TomBlodget 5.3 是不确定的,我现在已经澄清了这一点。我仍在努力解决 5.1 的评论。

以上是关于为啥我的 LUA 解释器不能处理字符串键值?的主要内容,如果未能解决你的问题,请参考以下文章

lua 与 c++或者c 交互的底层原理谁能解释一下?最最底层的,为啥它们调用C或者C++的函数?

为啥用 lua 替换 luajit

为啥 python 解释器不能在 Zeppelin 0.8.0 上为我的任何笔记本工作?

为啥 Skia 包含 Forth 解释器?

为啥 Lua 数组(表)从 1 而不是 0 开始?

为啥 type(nil)==nil 是假的?