引用Lua中包含表的函数

时间:2012-09-20 15:15:14

标签: lua closures

我有一个辅助函数,它返回一个这样的表:

function of_type(expected_type)
    return {
        expected = expected_type,
        matches = function(value) return type(value) == expected_type end,
        describe = "type " .. expected_type
    }
end

现在这对其他匹配器来说很好,但是在这里我想在调用type(value)函数时将matches存储到同一个表中的一个字段中。像这样:

function of_type(expected_type)
    return {
        expected = expected_type,
        mismatch = nil, -- set it to nil on initialization
        matches = function(value) 
            mismatch = type(value)  -- how to do this?
            return type(value) == expected_type
        end,
        describe = "type " .. expected_type
    }
end

这可能吗?

2 个答案:

答案 0 :(得分:2)

是的,但您需要将其拆分为以下步骤:

function of_type(expected_type)
    local tbl = {
        expected = expected_type,
        mismatch = nil, -- set it to nil on initialization
        describe = "type " .. expected_type
    }
    tbl.matches = function(value) 
        tbl.mismatch = type(value)
        return type(value) == tbl.expected
    end
    return tbl
end

-- testing it
local foo = of_type("string")
print(foo.matches(1), foo.matches("1"))

这应该按照您的预期输出false true

基本上,tbl.matches将存储对tbl的引用(称为“upvalue”),并且能够修改该表中的所有字段(包括对其自身的引用)。 / p>

执行此操作的另一种方式如下(请注意tbl.matches函数中的更改)。您可以使用tbl:method语义并将tbl作为隐式self参数传递而不是将其作为upvalue捕获:

    function of_type(expected_type)
        local tbl = {
            expected = expected_type,
            mismatch = nil, -- set it to nil on initialization
            describe = "type " .. expected_type
        }
        function tbl:matches(value) 
                self.mismatch = type(value)  -- how to do this?
                return type(value) == self.expected
            end
        return tbl
    end

local foo = of_type("string")
print(foo:matches(1), foo:matches("1"))

这将打印相同的结果。请注意,您使用foo:matches表示法将foo作为第一个参数传递(在方法中引用为self)。这与使用foo.matches(foo, 1)相同。

答案 1 :(得分:1)

你没有。好吧,不是没有存储表的副本,或者将表作为参数传递给表。在处理完表结构的所有语句之前,该表尚不存在。而且由于你从未将它存储在任何地方(在这个函数中),你的函数不能命名它以便找到它。

所以你应该给它一个名字,即使只是片刻:

function of_type(expected_type)
  local temp = nil
  temp = {
        expected = expected_type,
        mismatch = nil, -- set it to nil on initialization
        matches = function(value) 
            temp.mismatch = type(value)  -- Like this
            return type(value) == expected_type
        end,
        describe = "type " .. expected_type
    }
  return temp
end

这是有效的,因为Lua会将temp存储为upvalue。因此,您正在创建的函数将在temp中看到更改,例如将其设置为表值时。因为它是一个局部变量,所以在这个函数之外它是不可见的。