分配给变量的函数何时实际计算?

When are functions assigned to a variable actually computed?

我正在对我昨天编写的 Lua 函数进行一些故障排除,作为使用 Love2D API 的游戏开发工作的一部分。该函数旨在处理在具有 PG 地形的基于图块的 roguelike 类型系统中绕过障碍物的暴民实体。代码在下面,虽然我主要不是在这里寻找语法帮助,它只是为了上下文。故障排除在我脑海中提出了一个有趣的问题,我无法在 Lua 的文档中找到答案。

好奇的是,这个特殊的函数在一组 8 个方向上检查任何给定方向的障碍物的“左”和“右”,查看该方向上的广场是否包含可步行的地形,然后走到它上面如果是这样。如果两个方向都清晰,则掷硬币。如果两者都被阻止,它会放弃(现在,用于测试目的)。

我在一个(已确认工作的)实体 class 中定义它,因此所有的“自我”糖。 Move、canMove、Wander也都是Entity确认的工作方式

ObstructionHandler = function(self, x_direction, y_direction)
    local direction = {
        x = x_direction,
        y = y_direction
    }
    local direction_list = {{0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}}

    local check1 = nil
    local check2 = nil
    local move1 = nil
    local move2 = nil
        
    for i = 1, #direction_list do
        if direction.x == direction_list[i][1] and direction.y == direction_list[i][2] then
            if i == 1 then 
                check1 = self:canMove(direction_list[#direction_list][1], direction_list[#direction_list][2])
                move1 = self:Move(direction_list[#direction_list][1], direction_list[#direction_list][2])
            else
                check1 = self:canMove(direction_list[i - 1][1], direction_list[i - 1][2])
                move1 = self:Move(direction_list[i - 1][1], direction_list[i - 1][2])
            end
            
            if i == #direction_list then
                check2 = self:canMove(direction_list[1][1], direction_list[1][2])
                move2 = self:Move(direction_list[1][1], direction_list[1][2])
            else    
                check2 = self:canMove(direction_list[i + 1][1], direction_list[i + 1][2])
                move2 = self:Move(direction_list[i + 1][1], direction_list[i + 1][2])
            end
                if check1 and check2 then
                    if math.random(0,1) <= 0.5 then
                        move1
                    else -- this is where the error pops
                        move2
                    end
                elseif check1 then
                    move1  
                elseif check2 then
                    move2
                else
                    self.boredom = self.boredom + 1
                    self:Wander()
                end
            end 
    end
end

我收到的错误是“else”附近应该有一个等号。当我不正确地调用一个函数,或者当某处无法关闭括号时,我已经看到过这些类型的事情弹出。在检查了这类事情之后,我尝试将“self:”糖从声明中移到我实际调用函数的地方,即:

...
            if i == #direction_list then
                check2 = canMove(direction_list[1][1], direction_list[1][2])
                move2 = Move(direction_list[1][1], direction_list[1][2])
            else    
                check2 = canMove(direction_list[i + 1][1], direction_list[i + 1][2])
                move2 = Move(direction_list[i + 1][1], direction_list[i + 1][2])
            end
                if self:check1 and self:check2 then -- this is where the error pops in this version
                    if math.random(0,1) <= 0.5 then
                        self:move1
                    else
                        self:move2
                    end
                elseif self:check1 then
                    self:move1
                elseif self:check2 then
                    self:move2
                else
                    self.boredom = self.boredom + 1
                    self:Wander()
                end
...

我发现这样做真正有趣的是它改变了错误。当 运行 这样设置时,喜欢 returns 错误“'and' 附近预期的函数参数”。我仔细检查了 canMove 和 Move,他们在这里获得了他们需要的所有参数。然而,这让我开始思考:Lua(and/or Love)什么时候真正计算函数的结果,当函数被分配给一个变量时?

如果我说a = f(x),是不是运行ning f(x)然后,然后将输出分配给 a ?还是等到我稍后调用 a 到 运行 f(x)?还是两者兼而有之,比如如果我先声明然后再调用它,是否会重做这项工作?

如果有任何勇敢的人想帮助修复我的代码,那太棒了,但我会及时解决的;我主要感兴趣的是关于分配和计算的这个令人毛骨悚然的事情,因为现在我想到了它,它让我发疯,不知道。

move 不是有效的 Lua 语句。您不能只自己编写一个标识符。你需要把它和其他东西结合起来。

添加 self: 不会改变这一点。它只是将本地 move1 替换为 table 元素。这仍然是一个无效的表达式。

唯一改变的是 Lua 现在需要参数,因为冒号语法仅与函数结合使用。

如果move1是一个函数值你可以调用

move1()

或者如果它是 table self 的方法,您可以调用

self:move1()

但是只写 move1 在语法上是不正确的。 move2.

相同

If I say something like a = f(x), is it running f(x) there and then, and assigning the output to a at that time? Or does it wait until I later call on a to run f(x)? Or is it both, like is it redoing that work if I start with a declaration and then later call on it?

函数调用发生在运行时。函数定义也是如此,它也只是一个赋值。你的程序是从上到下逐行执行的

首先,您调用的变量没有括号。所以将 self:move1 更改为 self:move1(),它可能会修复错误