1. I am trying to replicate AceEvent-3.0's UnregisterEvent and UnregisterAllEvents using table.remove, as Rift uses table.insert to register events. There is a great deal of information provided here, but thus far haven't had any responses.

    The short of it is I would like to create a library file that introduces those two APIs, but I'm not sure how to use table.remove correctly in this case. For the first one, I am thinking it might be something like

     function lib:UnregisterEvent(Event, Identifier)
        if type(Event) ~= "table" then
            error("The event %s is not a table", Utility.Serialize.Inline(Event), 2)
        elseif type(Identifier) ~= "string" then
            error("The Identifier %s is not a string", Identifier, 2)
        end
        for i, value in pairs(Event[Identifier]) do
            value[i] = nil
        end
     end
    

    I am not quite certain where to use Utility.Dispatch, and while I am not certain if the above will work, I definitely don't know what I am doing to create UnregisterAllEvents specifically for one Identifier (or addon).

    Any suggestions welcome.

    Also, I just want to thank you (again) for the books, the site, and all your help and documentation. Over in WoW, without your help, I never would have got SmartRes2 up and running.

  2. With Utility.Dispatch, I think the first one might look like

     function lib:UnregisterEvent(Event, Identifier, [func, funcDesc]) -- func is optional
        if type(Event) ~= "table" then
            error("The event %s is not a table", Utility.Serialize.Inline(Event), 2)
        elseif type(Identifier) ~= "string" then
            error("The Identifier %s is not a string", Identifier, 2)
        end
        for i, value in pairs(Event[Identifier]) do
            value[i] = nil
        end
        if func then
            if type(func) ~= "function" then
                error("The function %s not a function", func, 2)
            elseif type(funcDesc) ~= "string" then
                error("Function description %s is not a string", funcDesc, 2)
            end
            Utility.Dispatch(func, Identifier, funcDesc)
        end
     end
    
  3. It depends entirely on how event registration is done behind the scenes. The following might show you how to register and then unregister a single event.

     -- Register an event
     local eventTbl = {function, "Identifier", "function description string"}
     table.insert(Event.Name, eventTbl)
    
     -- Unregister that event
     for idx, eventData in ipairs(Event.Name) do
       if eventData == eventTbl then
         table.remove(Event.Name, idx)
         break
       end
     end
    

    So perhaps something like this:

     -- Removes all event registrations in eventName with the given identifier
     function lib:UnregisterEvent(eventName, identifier)
       local i = 1
       while i < len(eventName) do
         local data = eventName[i]
         if data[2] == identifier then
           table.remove(eventName, i)
         else
           i = i + 1
         end
       end
     end
    
  4. Hmm, interesting. I was doing some more thinking, and here is my modified and updated pastebin. The problem that is making me seek help is that not everybody breaks up the table.insert into two pieces. Most authors are simply doing table.insert(Event.Some.Thing, {function, "Identifier", "func string"}) Therefore simply removing elements doesn't seem likely. The result is the same, but the implemtation is different. The second issue is that all events are named Event.Some.Thing, Event.Some.Other, etc, when trying to remove all events, I am looking for a way to match a string "Event.*" without knowing what the ".*" could be. And that brings up matching a table name with a string, which is another bag of tricks I haven't mastered.

    It wouldn't do to simply match all the Event.* stuff for all addons; as your code pointed out, it would have to be specifically targeting an identifier.

    I get why Trion is using tables, besides being different; it makes adding new return values to them, or deleting obsolete entries, very easy on their end. Same thing with their Inspectors, which is their version of WoW's GetSomeData. A table again. On the other hand, it also creates a need for this library because they either can't, or won't, build in the functionality.

  5. What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.

     -- Remove all entries for 'Identifier' from all events under this one. For
     -- example, if you call UnregisterForAllIdentifier(Event.Foo, "Blah") and
     -- there are events Event.Foo.Bar and Event.Foo.Bar.Baz, then this will remove
     -- any registrations for "Blah" from all of those events.
    
     function UnregisterAllForIdentifier(event, identifier)
        -- First remove any event registrations with this identifier from this
        -- level (i.e. from Event first). This code can be much easier if you can
        -- guarantee that each Identifier will only be registered for a given
        -- event exactly once.
        local idx = 1
        while idx < #event do
            local data = event[idx]
            if data[2] == identifier then -- check if the identifier matches
                table.remove(event, idx)
            else
                idx = idx + 1
            end
        end
    
        for key, value in pairs(event) do
            if type(key) == "string" then
                -- This should be "Foo" from event.Foo, so we want to recurse
                UnregisterAllForIdentifier(value, identifier)
            end
        end
     end
    
  6. What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.

    I didn't have a complaint or concern, sorry about the confusion. I had just posted my pastebin at the same time you had answered. A crossing in the interwebs, as it were.

    The code you just posted is the equivalent for UnregisterAllEvents(identifier), yes? How does my code for UnregisterSingleEvent stack up? I will try your code and let a few other authors give it a whirl.

  7. What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.

    I didn't have a complaint or concern, sorry about the confusion. I had just posted my pastebin at the same time you had answered. A crossing in the interwebs, as it were.

    The code you just posted is the equivalent for UnregisterAllEvents(identifier), yes?

    Only if you call it like MyLongFunctionName(Event, "Identifier"). You can wrap it however you want, but it just vacuously takes a table and scrubs all registrations for "Identifier" from that event, and all subevents.

    How does my code for UnregisterSingleEvent stack up? I will try your code and let a few other authors give it a whirl.

    Get rid of the recursion (the second loop) and that will unregister all registrations for the given identifier from the given event, again, called MyLongFunctionName(Event, "Identifier").

    So to unregister "Foo" from Event.Unit.Health you'd do:

     MyLongFuncName(Event.Unit.Health, "Foo")
    

    You can even make the recursive part of it a parameter as well, to simplify your code and allow more re-use.

  8. I think I get it, hopefully. The end results would be two functions in the lib (I added the key = function, since you'd want to get rid of those too).

      -- Remove all entries for 'Identifier' from all events under this one. For
      -- example, if you call UnregisterForAllIdentifier(Event.Foo, "Blah") and
      -- there are events Event.Foo.Bar and Event.Foo.Bar.Baz, then this will remove
      -- any registrations for "Blah" from all of those events.
    
     function UnregisterAllForIdentifier(event, identifier)
         -- First remove any event registrations with this identifier from this
         -- level (i.e. from Event first). This code can be much easier if you can
         -- guarantee that each Identifier will only be registered for a given
         -- event exactly once.
         local idx = 1
         while idx < #event do
             local data = event[idx]
             if data[2] == identifier then -- check if the identifier matches
                 table.remove(event, idx)
             else
                 idx = idx + 1
             end
         end
    
         for key, value in pairs(event) do
             if type(key) == "string" or type(key) == "function" then
                 -- This should be "Foo" from event.Foo, so we want to recurse
                 UnregisterAllForIdentifier(value, identifier)
             end
         end
     end
    
     function UnregisterSingleEventForIdentifier(identifier)
        for key, value in pairs(event) do
             if type(key) == "string" or type(key) == "function" then
                 -- This should be "Foo" from event.Foo, so we want to recurse
                 UnregisterAllForIdentifier(value, identifier)
             end
         end
     end
    

    The next two would be called in MyAddon.lua, depending on what you wanted.

     lib:UnregisterSingleEventForIdentifier(identifier)
     lib:UnregisterAllForIdentifier(event, identifier)
    
  9. Oh yes, you mentioned about each identifier being registered once per event: that is fair to assume, as you wouldn't register for the same event multiple times in the same addon, but different addons might register for the same event. Kind of like PerfectRaid and Pitbull both register for UnitHealth, but neither registers for UnitHealth more than once.