【问题标题】:Lua - Is it possible to check if 2 functions are equal?Lua - 是否可以检查两个函数是否相等?
【发布时间】:2015-08-24 15:33:16
【问题描述】:

是否有可能以字节为单位获取函数的大小以查看它是否与类似于 C++ sizeof 运算符的另一个函数匹配,或者以其他方式评估两个函数以查看它们是否相等而不实际知道函数/是?示例:

local function equals(func1, func2)
   -- check them and return true if equal
end

如果这不可能,就说,这将满足我的回答! 谢谢!

编辑:我需要检查一个函数的主体,看看它是否与另一个函数的主体相同。内存中的引用会有所不同,因此我不能使用“==”,但函数的引用名称可以不同。

【问题讨论】:

  • function f(x) return x+1 endfunction g(x) return x+1 end 是否相等?
  • 是的,这会奏效。关键参考 f 和 g 实际上并不重要。我只是在寻找一种方法来检查身体是否相等。
  • 那是不可能的,除非你有来源。一个函数可能是从字节码加载的。
  • sizeof 运算符不能用于比较 C++ 中函数是否相等。
  • 你想用这个解决什么实际问题?

标签: function lua byte equals


【解决方案1】:

对函数使用== 只会检查它们是否引用了相同的函数,这不是您所期望的。

这项任务相当困难,如果不是不可能的话。对于非常简单的情况,这里有一个想法:

function f(x) return x + 1 end
local g = function(y) return y + 1 end

fg 是根据您的定义相等的两个函数。假设文件是​​t.lua,运行:

luac -l t.lua

输出是:

main <t.lua:0,0> (4 instructions at 00000000003081c0)
0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 2 functions
        1       [1]     CLOSURE         0 0     ; 0000000000308330
        2       [1]     SETTABUP        0 -1 0  ; _ENV "f"
        3       [2]     CLOSURE         0 1     ; 0000000000308dc0
        4       [2]     RETURN          0 1

function <t.lua:1,1> (3 instructions at 0000000000308330)
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions
        1       [1]     ADD             1 0 -1  ; - 1
        2       [1]     RETURN          1 2
        3       [1]     RETURN          0 1

function <t.lua:2,2> (3 instructions at 0000000000308dc0)
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions
        1       [2]     ADD             1 0 -1  ; - 1
        2       [2]     RETURN          1 2
        3       [2]     RETURN          0 1

如你所见,这两个函数在虚拟机中的指令是一样的。

【讨论】:

  • 感谢您的解释。我认为这是我将得到的最接近的。很遗憾没有更简单的方法,但我必须凑合:)
  • 如果访问字节码让您更接近解决方案,那么有lbci,一个由@lhf 编写的字节码检查器库(用于 Lua 5.1 和 5.2,也可通过 LuaRocks 安装),它可以提供您与上述luac -l 的信息相同。
【解决方案2】:

会比较字节码吗?

local function equals(func1, func2)
    return string.dump(func1) == string.dump(func2)
end

当然,在某些情况下上述方法会失败。例如:

local function f1 (...)
    local a = print
    a(...)
end

local function f2 (...)
    print(...)
end


local function equals (f1, f2)
    return string.dump(f1) == string.dump(f2)
end

print(equals(f1,f2))   --> false

这两个函数做同样的事情,但它们生成不同的字节码。也许如果你陈述你想要达到的目标,可以提供比功能比较更好的解决方案。

【讨论】:

  • 抱歉回复缓慢。我必须检查两个表是否相同,以便如果它们没有出现在另一个表中,则只添加一个表的新条目,并且我可以轻松比较一个值是否已经在另一个表中,但函数要复杂得多,因为 == 只比较内存地址。
  • string.dump 即使这样做也会失败:function a() end function b() end print(string.dump(a) == string.dump(b)) 输出 false
  • 您应该在比较之前从转储中删除调试信息:string.dump(f1, true) == string.dump(f2, true)。它在 LuaJIT 上完美运行(但由于某种原因不适用于 Lua 5.3)。
  • 不知道“strip”调试标志(在 Lua 5.3 中引入)。谢谢。令我惊讶的是于浩的例子失败了。
猜你喜欢
  • 1970-01-01
  • 2013-12-02
  • 2018-09-05
  • 2020-02-12
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多