I have a table that contains many different classes. I would like to use these classes directly from the module that connects this table without referring to parents ( Window instead of app.gui.Window ).

Here is the simplest example of what I need:

 t = { a = 1, b = 2, c = 3 } function f(t) print(tb) -- так работает print(b) -- как заставить работать так? end f(t) 

UPD: Of course, the easiest way would be to solve the problem in the following way: b = tb , but let's agree that I don’t know the names of the keys from the table t in advance (more precisely, they certainly are known to me, but a = ta; b = tb; c = tc ... z = tz - this is some kind of govnokod).

Here is a solution that just occurred to me:

 function f(t) print(tb) -- так работает for k, v in pairs(t) do _G[k] = v end print(b) -- и так работает! end 

... But, as you see, it affects the global scope, not the local one, and this is unacceptable! I need a local analogue of _G , some _L .

There is an idea to create such a variable and register in its metamethods debug.getlocal and debug.setlocal , although I haven’t really figured out the syntax of these functions and in metamethods it is not yet strong, but I will try.

  • local Window=app.gui.Window and then use Window or even without local - Mike V.
  • @MikeV. Well, yes, this is the most obvious solution, but this option does not suit me. The list of classes will be expanded, I do not know in advance all their names. I would just like to extract all its contents from the table. - Beast Winterwolf
  • @MikeV. Updated the question. - Beast Winterwolf

1 answer 1

I will try to suggest implementing the scope through the module, put the code in the test.lua file:

 module('test', package.seeall) t = { a = 1, b = 2, c = 3 } for k,v in pairs(t) do _M[k] = v -- вынимаем переменные из таблицы в область видимости модуля _M end print(tb, b) -- 2 2 

as an example, call the module and check the global variable b :

 b = 4 local test = require "test" print(test.tb) -- 2 print(test.b) -- 2 ( b в модуле ) print(b) -- 4 ( b глобальная ) 

2 method using metatables and inheritance:

 local _M = {} setmetatable(_M, {__index = _G}) setfenv(1, _M) t = { a = 1, b = 2, c = 3 } for k,v in pairs(t) do _M[k] = v end print(tb, b) -- 2 2 return _M 

if you call this file using require result will be the same, the disadvantage is the extra overhead of inheritance _G.

and 3 way, you can set the scope with only setenv, but then you need to explicitly call functions through a _G.pairs type, which is not quite nice:

 local _M = {} local _G = _G setfenv(1, _M) t = { a = 1, b = 2, c = 3 } for k,v in _G.pairs(t) do _M[k] = v end _G.print(tb, b) -- 2 2 return _M 
  • It should be noted that since version 5.2, setfenv 5.2 is setfenv longer used. - val
  • @val yes, but there are workarounds, though not tested. - Mike V.
  • In this case, there is no need for a workaround; it suffices to replace setfenv(1, _M) with _ENV = _M - val
  • @val here agree - Mike V.
  • @MikeV. I am afraid that no option works the way I would like it to be in an ideal form, but it seems that there is nothing better to think of. Thank you very much! - Beast Winterwolf