动态定义LUA函数的正确方法

我最近一周一直在使用Lua,最终编写了这段代码。我发现可以动态创建新函数并从其他函数“继承”,所以程序员必须给它命名。我的问题是:

这被称为什么?

是否有更好的方法来完成此任务?(循环遍历数据结构并创建“改进”现有函数的插件函数)

D = {
  name = {
    value = nil,
    offset = 0,
    update = function (self)
      self.value = "Berlin"
    end,
  },
}

--动态函数定义
for i in pairs(D) do
  D[i].upAndWrite = function(self)
    self:update()
    print("upAndWrite was here")
  end
end

print(D.name.value)
D.name:upAndWrite()
print(D.name.value)

结果:

nil
upAndWrite was here
Berlin

原文链接 https://stackoverflow.com/questions/57255454

点赞
stackoverflow用户5697743
stackoverflow用户5697743

我认为你所做的没有特别的名称,只是即时创建函数。

关于你的代码,有几个要注意的地方:

正确的循环

for i in pairs(D) do
...
end

在编程中,变量i通常用于计数循环,例如:

for i=1,100 do
...
end

在这里,pairs返回一个迭代器函数,并且惯用的用法是

for k,v in pairs(D) do
...
end

这里,k是键(类似于你的代码中的i),而v是值(当你需要访问对应值时,请使用它而不是像D[k]D[i]这样的表索引)。

没有必要即时创建函数!

另一件重要的事情是,你在每个循环迭代中创建了新函数。虽然这个特性非常强大,但是你根本没有使用它,因为你没有使用upvalues存储任何东西,并且仅通过参数访问数据。

更好的方法是创建一个函数并将其分配给每个字段:

--在这里定义D

do
    local function upAndWrite(self)
        self:update()
        print("upAndWrite was here")
    end

    for k,v in pairs(D) do
        v.upAndWrite = upAndWrite --使用我们的函数
    end
end

--在这里执行测试

即时创建函数允许做什么?

如上所述,您可以在某些情况下利用这个非常强大的闭包机制。这里是一个简单的例子:

local t = {}

for i = 1, 100 do
    --创建函数以打印我们的值
    t[i] = function() print(i) end

    --创建将值增加一的函数
    t[-i] = function() i=i+1 end
end

t[1]()   --打印1
t[20]()  --打印20
t[-20]() --将upvalue增加1
t[20]()  --现在是21!

这个例子演示了upvalues的一个可能用法,以及许多函数可以共享它们的事实。这可以与事实一起在多种情况下使用,即upvalues不能被旁白代码更改(不使用debug库),并且通常是可信的。

希望我的回答可以覆盖你想知道的内容。

注意:此外,这种语言称为[Lua而不是LUA](https://www.lua.org/about.html#name)。

2019-07-29 15:43:55
stackoverflow用户4984564
stackoverflow用户4984564

作为一个整体,它没有一个名称。有很多概念参与其中:

  • 头等函数,也称为可以分配给变量并像数字或字符串一样传递的函数。
  • 匿名函数,也称为没有明确给它命名的函数。Lua 中的所有函数都是_技术上_匿名的,但通常它们在创建后立即分配到一个变量中。
  • 元编程,即编写编写程序的程序。创建函数(或方法)的循环在任意数量的对象上是非常简单的,但我会将它视为元编程。
  • Lua 表;这似乎是显而易见的,但请考虑并非所有语言都具有这样的功能。Javascript 有_对象_类似,但例如 Ruby 没有可比较的功能。

如果你要使用 pairs,你可能也要利用两个变量。

for key, object in pairs(D) do
  function object:upAndWrite(self)
    self:update()
    print("upAndWrite was here")
  end
end

虽然这会创建许多闭包,这意味着垃圾收集器会更加繁重,内存使用量和执行速度会更慢。

for key, object in pairs(D) do
  print(object.upAndWrite) -- 所有的函数都不同
end

这是一个不错的第一阶段,但在重构一下之后,你可以得到这个:

do
   local method = function(self) -- 仅创建一个闭包
      self:update()
      print("upAndWrite was here")
   end

   for key, object in pairs(D) do
      object.upAndWrite = method -- 多次使用一个闭包
   end
end

现在只有一个闭包被所有表共享。

for key, object in pairs(D) do
  print(object.upAndWrite) -- 所有的函数都是相同的
end
2019-07-30 06:12:03