Well, generally, if you’re updating every frame, you don’t care if two objects are still touching / not touching. You only care if the state changes, touching -> not touching or vice versa. To determine that, you need to remember what the previous state was for comparison. (Box2D will have to do this somehow, too.)
At first, of course, nothing is touching anything else.
The combo key is just a way of indexing both things together. Something that can be reliably reproduced just from the items. The swap just avoids having to waste time checking two different possible keys (depending on which object was first and which second).
If touching and colliding are both true, nothing has changed; ditto if they’re both false. Thus the “if not touching == colliding then” test. (That has the side benefit of turning any nil -valued touching to true , so you’re safely comparing two booleans and it’s fine that IsTouching starts out empty.)
The event dispatch tells anybody who’s interested that “began” or “ended” happened. I sent it through Runtime, but you could send it via each object or whatever. (Or through a series of tubes.) Also, less ambiguous event names would be better, I suppose. 
An alternative to the combo key / IsTouching set, and possibly more intuitive, is to keep a per-object touching set. Then you might have something like:
function objCollisionControl() local touching = obj1.m\_touching[obj2] assert(touching == obj2.m\_touching[obj1]) -- if this isn't true something's broken! local colliding = rectCollisionTrue(obj1, obj2) if not touching == colliding then -- did the state change? local event = { obj1 = obj1, obj2 = obj2 } if touching then event.name = "began" obj1.m\_touching[obj2] = true obj2.m\_touching[obj1] = true else event.name = "ended" obj1.m\_touching[obj2] = nil obj2.m\_touching[obj1] = nil end Runtime:dispatchEvent(event) -- As the notes say, write this however you like end end -- stuff local function RemoveTouchedObjects (event) local object = event.target for partner in pairs(object.m\_touching) do -- look at other objects we touched partner.m\_touching[object] = nil -- remove ourselves from other object's list end object.m\_touching = nil -- release our references end function NewObject () -- your object creation code... object:addEventListener("finalize", RemoveTouchedObjects) -- clean up after ourselves if removed object.m\_touching = {} -- keep track of touched objects return object end
The “finalize” stuff is just an attempt to handle objects getting removed mid-touch. There should be similar code in the previous example, but would actually be a chore to write. 
So this is similar to the previous approach, but you do a little more preparation when you create your objects, and the objects only need to know about their personal space. :) It’s a bit redundant in that the same data is maintained twice, but that’s not a big deal right now.