So I was curious and started to inspect code from Freya
which is a framework for Roblox. I was reading the code for Arbiters
and saw this code:
--code Controller.new = Hybrid(function(f) local newobs = newproxy(true) local omt = getmetatable(newobs) for k, v in pairs(ObserverMt) do omt[k] = v end ObserverCallbacks[newobs] = f ObserverEmitters[newobs] = Event.new() ObserverRules[newobs] = { } end) --more code
The part that I'm curious about is
local omt = getmetatable(newobs) for k, v in pairs(ObserverMt) do omt[k] = v end
I searched up on the wiki about newproxy
and all it does is create a blank userdata
.
Why not just do local omt = setmetatable({}, ObserverMt)
?
What does newproxy(true)
really do?
Does it have an effect on metatables
? If so, what is it?
newproxy(true)
produces a value of type "userdata"
, which means it is not a table.
Beyond having a different type(obj)
, this is significant because Lua distinguishes values by their type in a few inconvenient places.
The most noticeable distinction is that the __len
metamethod only applies to userdata which means if you want to override the behavior of the #
operator you must use newproxy(true)
to create the object.
(This was evidently seen as a mistake and is not the case in Lua 5.2)
As another minor example, a userdata object cannot be equal to (==
) a table object, since they have different types, even if they have the same __eq
metamethod.
Userdata has stronger protections
No, don't touch that
Even though Freya has this whole fundamental concept of open data, a lot of the objects rely on being locked down. Why, you ask? Two reasons:
Overall, the newproxy method can have a slightly larger memory footprint, but proper structure optimizations can nullify this and even present advantages over tables. Userdata also can't have any metamethod invocations bypassed through use of the rawset
and rawget
functions.
Back to the real question
The metatable must be set using getmetatable
because setmetatable
only works on tables. It's a small price to pay, given Roblox's modification of newproxy
to remove userdata templating.