I have a personal project and a pure lua writed object module which provides metatable with methods filter
map
etc to a table , I don't want to require and setmetatable for every line local foo={}
I have a personal project and a pure lua writed object module which provides metatable with methods
filter
,map
etc to a table , I don't want torequire
andsetmetatable
for every linelocal foo={}
.
You can avoid the need for require
by just ensuring that your "object module" is always loaded first, setting global variables. I consider require
to be cleaner however as it makes clear the dependencies of your files (and does not pollute the global environment).
To avoid the need for setmetatable
, you can write yourself a constructor function:
local metatable = ...
function Table(t) -- NOTE: global function
return setmetatable(t, metatable)
end
then, in another file which you ensure only runs after this file was executed:
local foo = Table{}
You might want to shorten Table
to T
if you use this very often.
First of all: You probably do not want local t = {}
to set a metatable on t
. This would mess with linters like Luacheck while also making your code hard to follow for everyone familiar with Lua but unfamiliar with this hack.
Setting a metatable with __index
also interferes with the usage of tables as dictionaries / hash maps; users now need to use rawget
/ rawset
to circumvent your metatable. Consider the following snippet:
local dict = { filter = "bar" }
print(dict.filter) -- "bar", as expected
print(dict.map) -- filter function - unexpected
print(rawget(dict, "map")) -- nil, as expected
It will also harm performance of every table access. Do you really want this just for some syntactic sugar?
Furthermore, if you heavily set metamethods (such as the arithmetic metamethods) even if it doesn't really make sense, you again get unexpected behavior by allowing passing tables where numbers are expected etc. Lua's partial strictness when dealing with incompatible types is what distinguishes it from JS.
how to automatically set default metatable to every newly created table?
This is not possible in general; the proper way to set metatables is to explicitly use constructors.
debug.setmetatable
, primitives & functionsUsing debug.setmetatable
, you can set "shared"/"common" metatables for all primitive types (boolean, number, string) as well as functions. You can not set a shared metatable for objects this way however.
This is what koyaanisqatsi's snippet does: It catches global variable access and sets the metatable on all new table global variables. This is insufficient as it forces you to use global/environmental variables, which is both bad for performance and code quality. It will in particular not work at all for local variables such as the local foo = {}
in your example. It will also not work for temporary variables in expressions (consider ({...}):filter(...)
).
The following approach would be more reliable than hooking environmental variable access:
{{}}
.Obviously this would be awfully slow. It is very likely that there still exist many "edge cases" this doesn't catch (what about table creation in C, for instance?).
The only proper solution would be to add such a feature - a default metatable for all tables - to the language by forking it and implementing this right in the function where Lua creates new tables. This is the only way this could be implemented adequately - that is, with adequate performance & reliability.