我有一个辅助函数,它返回一个这样的表:
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
的变化,例如当您将其设置为表值时。由于它是一个局部变量,因此在此函数之外不可见。