【问题标题】:Where to define table member functions in LuaLua表成员函数在哪里定义
【发布时间】:2019-07-15 10:02:12
【问题描述】:

据我了解,有多种方法可以在 Lua 中为表定义成员函数。例如,以下两个似乎是等价的:

-- method a)
local table1 = {x = 1, y = 2}
function table1:myfunc()
    return self.x + self.y
end

-- method b)
local table2 = {
    x = 1,
    y = 2,

    myfunc = function(self)
        return self.x + self.y
    end,
}

以前使用过 Python,我的直觉是使用方法 b) 将事物更整齐地组合在一起。但是,通过示例阅读,似乎人们通常按照惯例使用方法 a)。不过,我找不到任何客观的理由来说明为什么它应该是优越的。

确实,相反,在初始化表时,至少有理由向前声明函数变量,如下所示:

local table3 = {x = 1, y = 2, myfunc}
function table3:myfunc()
    return self.x + self.y
end

这样 Lua 从一开始就知道成员的存在,并且可以正确设置散列,而增加现有表的成员数量可能需要重新散列(尽管我无法想象这实际上会变成除非您对大量小表执行此操作,否则会出现明显的性能问题)。来源比较:https://www.lua.org/gems/sample.pdf

那么在定义表本身的过程中,有什么理由不直接定义成员函数呢?或者仅仅是因为某些语法糖(function name() 语法和冒号)不可用?

【问题讨论】:

  • table3 示例并没有按照您的想法进行。表构造函数{} 将复制要插入的值,读取变量myfunc 并将其存储在索引[3] 下。它不会创建稍后填写的myfunc 条目。如果您想创建该条目,请编写myfunc = true,以分配不是nil 的内容。但坦率地说,你不会在这里看到任何加速,只会浪费更多时间编写不需要的文本。另请注意,如果将所有方法函数存储在单独的表中,并将其设置为可对所有相同类型的对象进行元表处理,则更易于维护。
  • 方法a 允许您从函数内部访问变量table1 作为上值。方法 b 不允许这样做。
  • @Vlad 好吧,我想知道它应该如何区分前向声明和任何旧的未声明变量。并且看到table.member 相当于Lua 中的table["member"],我猜table3 = {1 = 1, y=2, "myfunc"} 也可以解决问题,对吧?
  • @EgorSkriptunoff 很公平,但是通过self 不会达到同样的效果吗?
  • @Vlad 再想一想,它可能不会成功,因为 Lua 仍然会将字符串存储在索引 3 下……

标签: lua lua-table


【解决方案1】:

作为一个函数式编程的书呆子,我更喜欢方法 b,因为它一次定义了表,而不是为我们需要添加的每个方法改变一次。您应该注意的一件事是,某些方法可能会相互调用,并且使用 locals 比调用 self:myfunc() 更快。

local function myfunc(self)
  return self.x + self.y
end

local myTable = {
  x = 1,
  y = 2,
  myfunc = myfunc,

  moreMyfunc = function(self)
    return myfunc(self) * 2
  end,
}

如果方法之间缺乏对称性很麻烦,您可以将所有方法设为本地并将它们添加到表构造函数中,就像我刚刚对 myfunc 所做的那样。

Egor 提出了另一个重要点(如果表是一个类,则更相关):

方法 a 允许您从内部访问变量 table1 作为上值 你的功能。方法 b 不允许这样做。

在这种情况下,我会转发声明表名。这样做的好处是改变一个变量一次,而不是多次改变表。

local myTable

local function myfunc(self)
  return self.x + self.y
end

local function moreMyfunc(self)
  return myfunc(self) * 2
end

myTable = {
  x = 1,
  y = 2,
  myfunc = myfunc,
  moreMyfunc = moreMyfunc,
}

【讨论】:

  • 好点,我没有考虑本地函数的速度差异。
  • 本地函数和非本地函数之间的速度差异完全在于它的搜索/查找机制,而不是执行。通过从方法中调用本地函数,您只需添加一个额外的间接。
  • 是的,函数就是值。值既不是本地的也不是非本地的。
  • 作为后续,如果我在本地函数中传递对象实例(即local function myfunc(self) do_stuff(self) end,那么如果我然后转到local function myfunctwo(self) self:myfunc() end而不是myfunc(self),会有什么不同吗?如果冒号只是语法糖,那么self:myfunc() 应该还是调用本地函数吧?还是它也会导致 Lua 在对象表中查找函数而不是使用本地函数?
  • 函数名只是变量(或表键)。速度差异是因为局部变量比表查找稍快。冒号是包含表查找的语法糖,所以它仍然比本地慢。
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 2011-05-17
  • 2017-06-13
  • 2011-06-17
  • 2014-10-29
相关资源
最近更新 更多