【问题标题】:How to understand metatable in Lua?如何理解 Lua 中的元表?
【发布时间】:2016-10-05 20:10:42
【问题描述】:

我用过 Python,但现在因为 Torch 正在学习 Lua。 “metatable”这个词对我来说真的很难理解。例如,元表是一种特殊的表吗?它如何改变表的行为?

【问题讨论】:

标签: lua torch metatable


【解决方案1】:

元表只是一个表,用于控制另一个表(或用户数据,或其他 Lua 值)的行为。一个表是一个元表只是因为它被使用作为一个元表。也就是说,作为“元表”不是表的基本属性。没有“create_metatable”函数或任何东西。它只是我们用来控制其他表的表的名称。

对表(或用户数据)的某些操作被指定首先检查表的元表。如果表(或用户数据)有一个元表,并且该元表中有一个特定的键/值对,那么操作将使用该键/值对来执行该操作,而不是正常的逻辑。

每个可以被元表覆盖的操作都有一个与之关联的特定键名。因此,如果您尝试对表执行添加操作,系统将在元表中查找 __add 键以访问它。

对中的值通常(但不总是)是一个函数。这样的函数通常被称为“元函数”。它采用的参数及其返回值的含义由调用它的特定操作定义。一些操作允许该值是一个表或其他东西。

在 Lua 中,您使用 setmetatable 函数将元表分配给表(但不是用户数据)。在 C 语言中,您使用 lua_setmetatable 函数为表(或用户数据)分配元表。

元表对于将 C 对象公开为用户数据的 C 代码尤为重要。原始用户数据只是一个不透明的位块; Lua 定义了非常少的可以默认对其执行的合法操作。但是通过给它们分配一个元表,你可以通过元函数赋予用户数据更多的能力。

请注意,除了表和用户数据之外的 Lua 值可以有元表。然而,与表和用户数据不同,每个 Lua 类型的值都共享该类型的 same 元表。所以所有字符串都有相同的元表,所有数字都有相同的元表,等等。

【讨论】:

    【解决方案2】:

    你好

    在阅读和理解什么是元表之后,我想发布一个工作示例。所以每个人都可以看到并感受到它的用处。该示例更改关联表的 # 运算符。因为我意识到 # 只计算正确的未命名键。 # 也忽略 0 和负数。这是一个工作示例,如何将其替换为对每个表进行正确计数的函数...

     # lua
    Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
    > -- Defining a table with 3 key/value pairs
    > my_table={[0]=0,[1]=1,['metatable']={}}
    > #my_table
    1
    > -- # is counting wrong it counts only my_table[1]
    > -- Now set the empty my_table.metatable to my_table
    > setmetatable(my_table,my_table.metatable)
    > -- So it can be accessed without getmetatable()
    > -- Now replacing # for associated table my_table
    > -- in my_table.metatable with the metafuncion __len
    > my_table.metatable.__len=function(array) local incr=0 for _ in pairs(array) do incr=incr+1 end return incr end
    > -- Let's test # ...
    > #my_table
    3
    > -- Now # is usefull because it counts correct
    > -- And my_table.metatable can be set as a metatable for other tables
    > -- where # is counting wrong but needed to count the correct way
    > #_G
    0
    > setmetatable(_G,my_table.metatable)
    > #_G
    45
    > #package.loaded
    0
    > setmetatable(package.loaded,my_table.metatable)
    > #package.loaded
    12
    > -- Like _G or package.loaded for example
    

    【讨论】:

    • "因为我意识到 # 只计算正确的未命名键。" 那是因为它不不应该。它确定表的数组部分的长度(整数键的序列从 1 单调增加到第一个 nil 条目)。这就是它的工作。
    • 是的,我同意,如果你知道,那么行为就很清楚了。但在这种情况下,“数组部分的长度”不是相关数组部分的长度。
    猜你喜欢
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 2015-07-07
    • 2018-11-14
    • 2021-06-13
    • 2011-12-14
    相关资源
    最近更新 更多