将本地变量作为参数调用匿名函数

我有一个函数创建一个对象(在这种情况下,是一个 Hammerspoon 的通知对象),我想将该对象作为参数传递给一个匿名函数,该匿名函数本身是一个函数调用的参数。

这是一个非常复杂的解释,但我认为一个例子可以表明问题。

function main()
    local n = hs.notify(...)
    print(n)          -- `hs.notify: Title (0x7fbd2b5318f8)`
    hs.timer.doAfter(1, function(n)
        print(n)      -- nil
        n:withdraw()  -- error: attempt to index a nil value (local 'n')
    end)
end

这样的输出是 n 第一次很好地打印出来(hs.notify: Title (0x7fbd2b5318f8)),但第二次,在匿名函数内部,它却为 nil 并抛出一个错误:attempt to index a nil value (local 'n')

这有些说得通,因为我从来没有真正地把它传进去。有没有一种方法可以将其传进去?hs.timer.doAfter 的签名是:hs.timer.doAfter(sec, fn) -> timerhttp://www.hammerspoon.org/docs/hs.timer.html#doAfter)。

点赞
用户301729
用户301729

匿名函数的定义包括声明一个名为 n 的参数,这会隐藏外部作用域中的 n 变量。函数声明创建了一个新的本地变量,如果没有传递参数到函数中它将为空,但调用匿名函数的定时器函数并不期望传递任何值,因此函数局部的 n 仍然为空。

你可以通过从匿名函数中简单地删除参数声明,但保留函数内部对 n 的使用来解决它。这样它将捕获来自外部作用域的 n 变量,该变量具有从 hs.notify(...) 返回的值。

function main()
    local n = hs.notify(...)
    print(n)          -- `hs.notify: Title (0x7fbd2b5318f8)`
    hs.timer.doAfter(1, function() -- <== 没有参数
        print(n)      -- nil
        n:withdraw()  -- error: attempt to index a nil value (local 'n')
    end)
end
2016-07-16 03:26:02