【问题标题】:attempt to compare nil with number stack traceback?尝试将 nil 与数字堆栈回溯进行比较?
【发布时间】:2019-11-06 17:36:10
【问题描述】:

我正在通过以下链接使用 Lua:https://www.lua.org/pil/4.2.html 并且对某一点感到困惑。

Lua 5.2.4  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> x=10
> local i=1
> while i<=x do
>>  local x = i*2
>>  print(x)
>>  i=i+1
>> end
stdin:1: attempt to compare nil with number
stack traceback:
    stdin:1: in main chunk
    [C]: in ?

我猜这个错误信息表明表达式while i&lt;=x 有问题。非常感谢任何 cmets。 编辑: 我只是意识到这可能是因为它在终端中不起作用。

【问题讨论】:

  • 无法在 repl.it 上重现它,代码没有任何问题
  • @AndrewKashpur repl.it 不提供控制台,但as you see 是可以运行的main.lua

标签: lua


【解决方案1】:

它在交互式终端中不起作用。因为local i=1 被终端理解为一个块,一旦你按下回车键。这就是“尝试将 nil 与数字进行比较”错误的原因;因为 i 未定义,即在这种情况下为零。要更正它,请将前两行和 while 循环放在 do chuck 中,如下所示。

> do
>>  x = 10
>>  local i=1
>>  while i<=x do
>>    local x = i*2
>>    print(x)
>>    i = i+1
>>  end
>> end
2
4
6
8
10
12
14
16
18
20
> 

【讨论】:

  • 有趣:do 显然开始了一个新的“本地人范围”或 Lua 术语中的 chunk
  • @Wolf do 开始一个block。从语法上讲,块是块,但它们的处理方式不同。块很好地控制变量的范围。无论如何,在 Lua 解释器中,您可以省略外部 do 块,以简化:local i = 1 while i &lt;= x do(在一行中)。
  • @kkxx 你可以接受你的答案是正确的。这没有什么可耻的。哈!该 IIRC 甚至还有一个徽章。
【解决方案2】:

其实问题出在local i=1试试

> local i = 1
> print(i)

问题在于,在运行控制台时,该行似乎是一个块,而变量是该块内的本地变量。 你可以通过使用全局变量来解决这个问题,或者你可以这样做

> local i = 1 do
>> print(i)
>> end

这会导致像这样[local i [print(i)]] 这样的块结构,因此可以访问 i。另请注意,local x = i*2 是有效的,因为它位于 while - do 块内。

如果您的代码在 Lua 文件中,它也可以正常工作。

【讨论】:

  • 我试过了,它在 Lua 文件中工作。问题是,在 Lua 文件中,如何定义“块”?
  • @kkxx 当你加载一个文件时,它的所有顶级内容都被认为是一个主块。看看吧:玩弄luac -l
  • @kkxx 当你使用if(关键字之间的部分if thenelseif thenelseend),whilefor以及function s 是单独的块。如果您想定义一个不满足任何这些功能的块(仅用于限制局部变量的范围),您始终可以使用do [chunk] end。例如,您还可以使用dofile() 执行另一个文件,其中执行的文件本身就是一个块。
【解决方案3】:

我也可以在 Lua 5.3.4 中重现该问题。

如果你继续阅读Lua docs, chapter 4.2 – Local Variables and Blocks,你会得到句子

请注意,如果您在交互模式下输入此示例,它将无法按预期工作。第二行 local i = 1 本身就是一个完整的块。

这正好解决了相关问题。因此,Lua 解释器似乎对最外层块(明显存在于 Lua 文件中)的支持有限。但考虑到语言和解释器的紧凑性,这种行为在我看来是可以接受和理解的。

所以,在交互模式下,

或者在变量 i 之前省略 local 以使其工作:

Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
Lua>x=10
Lua>i=1
Lua>while i<=x do
...>local x=i*2
...>print(x)
...>i=i+1
...>end

开始用一个块包围整个:

Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
Lua>do
...>local x=10
...>local i=1
...>while i<=x do
...>local x=i*2
...>print(x)
...>i=i+1
...>end
...>end

这两个选项都会产生常规(和预期的)输出:

2
4
6
8
10
12
14
16
18
20

【讨论】:

  • 这是因为当您在变量 i 之前省略 'local' 时,它被认为是全局的。然后 i 和 x 在 while 循环中都有要比较的值。
  • @kkxx 是的,很明显,感谢您查看它。同时,文档澄清了关于块和本地的混淆。
  • 我明白了。整个 Lua 文件被视为一个块。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
  • 1970-01-01
  • 2014-05-22
  • 2017-03-19
  • 2021-10-13
  • 2018-07-31
  • 2016-04-22
相关资源
最近更新 更多