为什么会出现这个错误? “试图索引本地变量…”

我是 Lua 的新手,正在努力理清思路。我尝试了这段代码:

function newCarousel(images)
    local slideToImage = function()
        print("ah!")
    end
end

local testSlide = newCarousel(myImages)
testSlide.slideToImage()

它给我返回了这个错误:

尝试索引一个本地的 "testSlide"(一个空值)...

这是为什么呢?

原文链接 https://stackoverflow.com/questions/6054018

点赞
stackoverflow用户501459
stackoverflow用户501459

因为 newCarousel 没有返回任何东西,所以 testSlide 是空的,因此当您尝试对它进行索引(testSlide.slideToImage 恰好等同于 testSlide["slideToImage"])时会出错。

我建议阅读《Lua程序设计》。你可能能够通过试错来工作语言的语法、语义和惯用法,但这会花费你更多的时间。

2011-05-19 05:38:16
stackoverflow用户282658
stackoverflow用户282658

你现在的代码,正如 Mud 所示,没有返回任何东西。(这不是像 Scheme 或 Ruby 那样,最后一个表达式的值是返回值。) 此外,你似乎认为 newCarousel 是一个对象。但其实不是。它是一个函数。当你完成对 newCarousel 的调用后,它就完成了它的工作,不管那是什么(在你的情况下,是创建一个很快被丢弃的局部变量,并返回 nil)。

正确的代码应该更像是:

function newCarousel(images)
    return function()
        print("ah!")
    end
end

local testSlide = newCarousel(myImages)
testSlide()

这里,我现在让 newCarousel 创建了一个(匿名)函数并立即返回它。这个匿名函数绑定到了 testSlide,所以只要 testSlide 在作用域内,我可以随时调用它。


在玩 Lua 时查看生成的代码很有教育意义。首先让我们看一下 luac 为您的代码生成了什么:

main <junk.lua:0,0> (8 instructions, 32 bytes at 0xeb6540)
0+ params, 2 slots, 0 upvalues, 1 local, 3 constants, 1 function
    1   [5] CLOSURE     0 0 ; 0xeb6720
    2   [1] SETGLOBAL   0 -1    ; newCarousel
    3   [7] GETGLOBAL   0 -1    ; newCarousel
    4   [7] GETGLOBAL   1 -2    ; myImages
    5   [7] CALL        0 2 2
    6   [8] GETTABLE    1 0 -3  ; "slideToImage"
    7   [8] CALL        1 1 1
    8   [8] RETURN      0 1

function <junk.lua:1,5> (2 instructions, 8 bytes at 0xeb6720)
1 param, 2 slots, 0 upvalues, 2 locals, 0 constants, 1 function
    1   [4] CLOSURE     1 0 ; 0xeb6980
    2   [5] RETURN      0 1

function <junk.lua:2,4> (4 instructions, 16 bytes at 0xeb6980)
0 params, 2 slots, 0 upvalues, 0 locals, 2 constants, 0 functions
    1   [3] GETGLOBAL   0 -1    ; print
    2   [3] LOADK       1 -2    ; "ah!"
    3   [3] CALL        0 2 1
    4   [4] RETURN      0 1

在您的代码中,主要部分创建了一个闭包,将其绑定到名称 newCarousel,获取该值,获取 myImages 的值并进行调用。这相当于 local testSlide = newCarousel(myImages)。接下来,它从本地表 (testSlide) 中获取了 slideToImage 的值。问题在于,testSlide 不是一个表,它是 nil。这就是你收到错误消息的地方。当然,这不是唯一的错误,但它是运行时看到的第一个错误,是让一切都被束缚的原因。如果您从 newCarousel 返回了一个实际的函数,您会得到不同的错误。例如,如果我向 newCarousel 函数添加了行 return slideToImage,则错误消息将是 "attempt to index local 'testSlide' (a function value)"。

2011-05-19 05:51:29
stackoverflow用户312586
stackoverflow用户312586

如果你想使用testSlide.slideToImage()你需要修改newCarousel让它返回一个包含一个函数的表格。最简单的实现如下:

function newCarousel(images)
    local t = {}
    t.slideToImage = function()
        print("ah!")
    end
    return t
end

你甚至可以在一个步骤中构建t并返回它;下面的代码等效于上面的代码:

function newCarousel(images)
    return {
        slideToImage = function()
            print("ah!")
        end
    }
end
2011-05-19 07:30:09