Skip to content
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

Closed
wants to merge 3 commits into from
Closed

Error when a nil key is indexed within an enum list #44

wants to merge 3 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Jan 15, 2022

Fixes #31.

@lucasmz-dev
Copy link

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

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))
Copy link
Owner

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.

Copy link
Owner

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.

Copy link
Owner

@Sleitnick Sleitnick Jan 21, 2022

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.

Copy link
Contributor

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.

Copy link

@lucasmz-dev lucasmz-dev Jan 23, 2022

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.

Copy link

@lucasmz-dev lucasmz-dev Jan 23, 2022

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.

@Sleitnick Sleitnick self-assigned this Jan 21, 2022
@Sleitnick Sleitnick added the enhancement New feature or request label Jan 21, 2022
@ghost ghost closed this by deleting the head repository Feb 9, 2023
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EnumList should error when trying to index a nil value within the Enums table
3 participants