引用在 Lua 中封装表的函数



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

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

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

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

这可能吗?

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

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"),并能够修改该表中的所有字段(包括对其自身的引用)。

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

    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) 相同。

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

所以你应该给它起个名字,哪怕只是片刻:

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存储为升值。因此,您正在创建的函数将看到temp的变化,例如当您将其设置为表值时。由于它是一个局部变量,因此在此函数之外不可见。

最新更新