syntax - 是否可以在 Lua 中复制 Ruby 的 method_missing?

标签 syntax lua metaprogramming method-missing

我相当确定在 Lua 中,您可以使用给定元表的 __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, name, ...)
    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 to 永远不会为零,因为我必须返回一个可以调用的对象才能pass the buck从索引函数到实际调用的潜在调用。

即在如上定义全局 method_missing 之后,尝试调用未定义的方法 'test_print' 会按预期运行,但索引时 test_print 的值为非 nil,以及其他未响应的方法/变量,例如 this_should_be_nil非零。

那么有没有可能避免这个陷阱呢?或者在不修改语言源本身的情况下,语法是否可以不弯曲来支持这种修改?我想困难在于如何在 Ruby 中索引和调用是类似的,而在 Lua 中它们是不同的。

最佳答案

您可以通过制作 nil 来避免这个问题。值可调用。
不幸的是,这只能从宿主代码(即 C 程序)中完成,而不能从 Lua 脚本中完成。

帕斯卡代码:

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

关于syntax - 是否可以在 Lua 中复制 Ruby 的 method_missing?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19776211/

相关文章:

c++ - 成员必须有类/结构/union

带参数的 Redis StackExchange LuaScripts

algorithm - 给定相对于球体的 X、Y 和 Z 向量,求出球体的自旋

c++ - 没有定义的类函数如何不导致错误

c++ - 如何避免简单的递归模板类型定义

javascript - 哪种语法对于 React 来说更典型(如果有的话)(版本 16)?

c - 在c中初始化一个新结构

c++ - 复杂的 C++ 模板语法

lua - 如何提取非固定字符串的数据

c++ - 我应该何时/为什么(如果有的话)考虑进行泛型编程/元编程