Skip to content
This repository has been archived by the owner on Dec 4, 2020. It is now read-only.

Add set constructor #385

Merged
merged 1 commit into from
Feb 26, 2020
Merged

Add set constructor #385

merged 1 commit into from
Feb 26, 2020

Conversation

ibm2431
Copy link
Contributor

@ibm2431 ibm2431 commented Feb 23, 2020

I affirm:

  • that I agree to Project Topaz's Limited Contributor License Agreement, as written on this date
  • that I've tested my code since the last commit in the PR, and will test after any later commits

@zach2good I'm coming for your Rhapsodies PR~!

Copy link
Contributor

@KnowOne134 KnowOne134 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would love it used in an example script in same PR

@ibm2431
Copy link
Contributor Author

ibm2431 commented Feb 26, 2020

So currently, a lot of scripts do something like this:

good_things =
{
    "cookies",
    "cake",
    "pie"
}

giveToNPC = function (player, npc, item)
    local gave_good = false
    for _, thing in pairs(good_things) do
        if thing == item then
            gave_good = true
            break
        end
    end
    if gave_good then
        player:showText(npc, I_LIKE_THIS)
    else
        player:showText(npc, I_DO_NOT_WANT)
    end
end

The above is quite silly. Every time a player gives an item to an NPC, you have to loop through the entire table every time - up to the number of items in the table if they did not give a good thing - and do your comparisons on every item until you find (or don't) the thing you're looking for.

So instead, with a set constructor - which builds a table of true values, with keys based on what you intend to compare against - you can check if something is a member of that "set" of items with a single operation. A key in the resulting table will return true, and if a key isn't in the table, the lookup will result in nil, evaluating to false:

good_things = set{
    "cookies",
    "cake",
    "pie"
}

giveToNPC = function (player, npc, item)
    if good_things[item] then
        player:showText(npc, I_LIKE_THIS)
    else
        player:showText(npc, I_DO_NOT_WANT)
    end
end

This results in code that's easier to follow, and saves processing time when your script is running later.

The astute reader might say, "but with the constructor, you're always going to loop through the entire table when you build the set". This is true - but if the set is being defined as part of a global which is then loaded via require, it will only be stepped through once. When Lua loads a script/package through require, it will keep it in memory (until an event happens which triggers garbage collection).

The end result is you go through all items in the set when initially creating the key->true table, but when your functions are called later, checking is just a single operation.

@ibm2431 ibm2431 changed the base branch from master to set February 26, 2020 21:34
@ibm2431 ibm2431 merged commit d4ba7d1 into project-topaz:set Feb 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants