1

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

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

这可能吗?

4

2 回答 2

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

执行此操作的另一种方法如下(注意 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).

于 2012-09-20T15:25:29.447 回答
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,例如当您将其设置为表值时。而且由于它是一个局部变量,所以在这个函数之外它是不可见的。

于 2012-09-20T15:26:56.590 回答