我很确定在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脚本完成.
不幸的是,这只能从主机代码(即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