语法 – 是否可以在Lua中复制Ruby的method_missing?

我很确定在Lua中,您可以使用给定的Metatable的__index,__ newindex和__call来粗略地复制 Ruby的method_missing.我有点:
function method_missing(selfs,func)

    local Meta = getMetatable(selfs)
    local f
    if Meta then
        f = Meta.__index
    else
        Meta = {}
        f = rawget
    end
    Meta.__index = function(self,name)
        local v = f(self,name)
        if v then
            return v
        end

        local Metahack = {
            __call = function(self,...)
                return func(selfs,name,...)
            end
        }
        return setMetatable({},Metahack)
    end

    setMetatable(selfs,Meta)
end

_G:method_missing(function(self,...)
    if name=="test_print" then
        print("Oh my lord,it's method missing!",...)
    end
end)

test_print("I like me some method_missing abuse!")

print(this_should_be_nil)

我的问题是:虽然语法类似,我当然可以使用它来复制功能,但它引入了一个突破性的错误.你在应用method_missing的表的上下文中使用的每个变量永远都不是nil,因为我必须返回一个可以被调用的对象,以便将潜在调用的降压从索引函数传递给实际的调用.

ie在定义了如上所述的全局method_missing之后,尝试调用未定义的方法’test_print’按预期运行,但是当索引时test_print的值是非零的,并且未响应的其他方法/变量,如this_should_be_nil是非零.

那么有可能避免这个陷阱吗?或者,如果不修改语言源本身,语法是否可以支持这种修改?我想象在Ruby中,索引和调用是如何类似的,而在Lua中它们是截然不同的.

解决方法

您可以通过使nil值可调用来避免此问题.
不幸的是,这只能从主机代码(即C程序)完成,而不能从Lua脚本完成.

Pascal代码

function set_Metatable_for_any_value_function(L: Plua_State): Integer; cdecl;
begin   // set_Metatable_for_any_value(any_value,mt)
   lua_setMetatable(L,-2);
   Result := 0;
end;

procedure Test_Proc;
   var
      L: Plua_State;
   const
      Script =
'set_Metatable_for_any_value(nil,' +
' {                                                                      ' +
'   __call = function()                                                  ' +
'              print "This method is under construction"                 ' +
'            end                                                         ' +
' }                                                                      ' +
')                                                                       ' +
'print(nonexisting_method == nil)                                        ' +
'nonexisting_method()                                                    ';
begin
   L := luaL_newstate;
   luaL_openlibs(L);
   lua_pushcfunction(L,lua_CFunction(@set_Metatable_for_any_value_function));
   lua_setglobal(L,'set_Metatable_for_any_value');
   luaL_dostring(L,Script);
   lua_close(L);
end;

输出

true
This method is under construction

相关文章

1.github代码实践源代码是lua脚本语言,下载th之后运行thmai...
此文为搬运帖,原帖地址https://www.cnblogs.com/zwywilliam/...
Rime输入法通过定义lua文件,可以实现获取当前时间日期的功能...
localfunctiongenerate_action(params)localscale_action=cc...
2022年1月11日13:57:45 官方:https://opm.openresty.org/官...
在Lua中的table(表),就像c#中的HashMap(哈希表),key和...