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

No way to check if key exists in map array in O(1) #466

Open
phobos2077 opened this issue May 23, 2023 · 2 comments
Open

No way to check if key exists in map array in O(1) #466

phobos2077 opened this issue May 23, 2023 · 2 comments

Comments

@phobos2077
Copy link
Collaborator

phobos2077 commented May 23, 2023

One array opcode is missing in sfall. There is no way in O(1) to distinguish if key exists in map array or if it's a 0. The only way is to call array_key on every index which is O(n). Also the array has to be created with a "lookup" flag, without it, you can't have 0 as value in the first place.

@phobos2077
Copy link
Collaborator Author

Suggestion:

  • Always allow to assign 0 value to maps.
  • Add 2 new opcodes: void unset_array(OBJECT, ANY) and INT array_is_set(OBJECT, ANY) to remove key from a map and to check if key exist, respectively.
  • Remove "lookup" flag (its looks like failed attempt to fix the root issue of not being able to distinguish 0).

@phobos2077
Copy link
Collaborator Author

phobos2077 commented Jul 12, 2023

After some more thinking, realized that there are very few cases where these opcodes are actually needed.

  • Whenever you need to use array as a hashset, just use 1 as value always and you get O(1) lookups no problem.
  • When you just want to store 0 value and then read it, it doesn't really matter if it's actual 0 or a function returns 0 because key doesn't exist - result is the same.
  • When you need to use 0 (mostly happens when dealing with enums like damage type, many start from 0) but also need to distinguish from no-value, you can just store -1 for no-value (which is standard practice for integers in C-like languages anyway).

Case I can think of when this might be needed:

  • You have an assoc. array where value can be 0
  • AND, you want to use the same array as a set, to check if key exists or not

For this case, there are workarounds like:

  • Store values as strings and using atoi (ugly).
  • Duplicate keys in a separate array with all 1 as values (also bad).
  • Whenever you set value, if it's a 0, store -1 instead (still bad).
  • Initialize values with -1 and to see if value is set or not use: if (x >= 0) instead of if (x). Might not work in all cases.

But I think the case like this is somewhat rare, and you need to add 2 opcodes (or metarules) to support it. Might be overkill.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant