-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error when a nil key is indexed within an enum list #44
Conversation
idk if performance is that important here but one of the ways you can make this faster is by using a if statement instead since it doesn't have to format the string that might not even be used, which is pretty slow |
modules/enum-list/init.lua
Outdated
local self = setmetatable({}, EnumList) | ||
local self = setmetatable({}, {__index = function(self, key) | ||
local val = EnumList[key] or rawget(self, key) | ||
assert(val, ("Key %s was not found in enum list"):format(key)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be an explicit val ~= nil
to avoid cases where val
could be false
potentially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not sure if rawget(self, key)
is needed there, since __index
will only fire if it failed to index a value with the given key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One possible solution could be to write the __index function as something like this:
local self = setmetatable({}, {
__index = function(t, k)
local v = Test[k]
return if v ~= nil then v else error(tostring(k) .. " is not an enum item", 2)
end
})
This would allow us to skip the assertion for class-table-level members but still throw an error if the value doesn't exist. As @LucasMZReal said, assertions w/ string formatting are notoriously slow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is needed as you would end up stack overflowing it if you did just self[key] directly, as it is possible that the key is entirely non existent in any of the tables.
I think what @Sleitnick meant with rawget(self, key)
being unnecessary is that, for __index
metamethod to fire in the first place, self[key]
must be nil.
This means rawget(self, key)
will always return nil, and as such the call is unnecessary as we already know it will return nil.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@finobinos It isn't a micro optimization. Assert is a function, any arguments you pass through it are always processed as it's called, even if the key exists, it will still do expensive string manipulation because it needs to pass that string anyway to assert. I can see people indexing Enums in things that run every frame. It doesn't make a difference to readability, and it saves people from having some real annoying time debugging performance for a really long time to just realize the library they're using is slowing down their program.
Yeah, if it only had a performance effect when an error happens anyway yeah it makes more sense to add debug info and spend time formatting a string, but that isn't the case here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually nevermind you're right but we both had our minds break, you treated it as if __index will always run but also not and it oofed my thinking. But yeah.
Wouldn't it better to have this work more similarly to GoodSignal though? Where the __index that fires when there's not a method is on the class table? It would be more performant to index class methods and wouldn't suffer with losing class auto complete.
Luau in Roblox somewhat understands classes when you have __index point to a table and it can show the methods for you as you have probably noticed. If the __index method is listening to indexing in the Class table (e.g. EnumItem
) then you don't suffer from that.
Fixes #31.