Syntax 我是否可以覆盖Lua表';它自身的返回值是多少?

Syntax 我是否可以覆盖Lua表';它自身的返回值是多少?,syntax,lua,overriding,lua-table,meta-method,Syntax,Lua,Overriding,Lua Table,Meta Method,当一个表在没有键的情况下被引用时,是否可能返回一个特定的值而不是对其自身的引用 假设我有下表: local person = { name = "Kapulani", level = 100, age = 30, } 在Lua中,我可以很容易地引用“person.name”、“person.level”或“person.age”,并获得预期的值。但是,在某些情况下,我可能只想引用“person”,而不是获取“table:”我想返回“person.name”的值 换

当一个表在没有键的情况下被引用时,是否可能返回一个特定的值而不是对其自身的引用

假设我有下表:

local person = {
    name  = "Kapulani",
    level = 100,
    age   = 30,
}
在Lua中,我可以很容易地引用“person.name”、“person.level”或“person.age”,并获得预期的值。但是,在某些情况下,我可能只想引用“person”,而不是获取“table:”我想返回“person.name”的值

换句话说,我希望person.x(或person[x])从表中返回适当的条目,但不带键的person返回person.name(或person[“name”])的值。有没有一种机制我没能找到

我在元表方面没有成功,因为_索引只适用于键不存在的情况。如果我把“person”放在一个单独的表中,我可以得出:

local true_person = {
    ... -- as above
}

local env_mt = {
    __index = function(t, k)
        if k == 'person' then
            return true_person
        end
    end
}

local env = setmetatable( {}, env_mt )
这让我可以使用_index做一些特殊的处理,除了无法从_index()判断我是收到对env.person的请求(我希望返回true_person.name)还是env.person[key](我希望返回true_person作为一个表,以便可以适当地访问“key”)


有什么想法吗?我可以用不同的方法来处理这个问题,但我希望我可以按照这些思路来处理这个问题。

当表被用作字符串时,可以通过设置
\uu tostring
元表条目来实现:

$ cat st.lua
local person = {
    name  = "Kapulani",
    level = 100,
    age   = 30,
}

print(person)
print(person.name)
print(person.age)

setmetatable(person, {__tostring = function(t) return t.name end})
print(person)

$ lua st.lua
lua st.lua
table: 0x1e8478e0
Kapulani
30
Kapulani

我不确定你所要求的是不是一个好主意,因为它与组成性背道而驰。通常,人们会期望以下两个程序执行相同的操作,但您希望它们的行为有所不同

print(person.name)

local p = person
print( p.name )
这项任务如何运作也不是很清楚
person.age=10
应更改年龄,但
person=otherPerson
应更改对perrson的引用,而不是年龄

如果您不关心组合性并且只读取数据,那么解决问题的更直接的方法是使用一个查询函数来接收编码为字符串的字段

query("person.age")   -- 17
query("person.name")  -- "hugomg"
query("person")       -- 17; query gets to default to whatever it wants.
为了使语法更轻量级,可以省略可选的括号

q"person.age"
q"person"
或者您可以扩展全局表上的
\uu index
元方法,
\u G

setmetattable(_G, { __index = function(self, key) return query(key) end })

print ( person_age )  -- You will need to use "_" instead of "." for the
                      -- query to be a valid identifier.

这是非常有用和直接的。如果默认值不是字符串,而是数字呢__tonumber似乎不是有效的元方法。是否有使用数值的变通方法?也就是说,可以使用age而不是name?@Kapulani,但我认为这是一个强大的契约,_-tostring应该返回一个字符串。metamethod名称用于正在执行的操作(和函数)。您当然可以从该元方法返回一个数字。正如@TomBlodget所说,这可能有点奇怪,但在大多数情况下,它不会损害任何东西(正常的字符串用例只会立即自动将数字转换为字符串)。唯一会造成伤害的是,如果有人试图直接对返回值使用字符串元方法/etc.。即使我劫持了u tostring,我也必须在许多地方强制调用tostring()(例如,如果我想让person返回person.age,而我正在进行person>21的比较)。我想我将放弃我的方法,但我将把这个标记为答案,因为它在技术上达到了我最初提出的要求。感谢您的有益评论。您正在与Lua的语法作斗争,以创建自己的DSL。这真的有什么好处吗?举个例子会有所帮助。无论如何,您可以尝试使用_call metamethod,或者简单地向所有这样的表添加一个:default()方法,使用常规或特定于表的实现。我一直在玩_; call,它有点接近我想要的,尽管我希望避免使用()。我希望的优点是,通过限制现有语法和Lua语法之间的“转换”量,当Lua抛出错误时,输出相对有意义,并且用户可以识别。因此,转换&to和| to或并没有那么奇怪,但在某些地方翻译成person to person()可能有点奇怪,因为person.name不需要翻译。