Official ScriptUO EasyUO Scripts > Scripting Chat

NameSpace Question: Maintaining namespace integrity with many:many relationship.

(1/3) > >>

lydaan:
I, like probably many, was very confused and intimidated by NameSpace management for a long time. I recently started managing sub-variable integrity manually, and the relevance of namespaces finally became clear.

Instead of passing variables %0-%n to a static %sub_variable, and then deleting them at the exit of the sub, EUO already has tools to manage this for you. By declaring a local namespace for the sub and clearing it and recalling the previous namespace, all that legwork is handled for you (for the majority of scenarios).

My question has to do with push/pop and I'm looking for confirmation or correction on what I understand to be limitations. I am not an expert, but I believe I have the logic of namespace worked out.


--- Quote ---*FYI*: For the context of this thread I will assume that any Sub will populate a sub-local namespace, and as such I will purposefully conflate "namespace," with "sub." I want to frame namespace management in the context of sub-local variable management so that namespaces novices like myself can more easily interpret a namespace use case.

This will likely be most people's first experience/need for NameSpace Management. The NameSpace function has more usages than sub-variable management, but grasping this specific usage will translate to understanding when other uses are necessary.

*Properly defining "many," without making assumptions (every sub will populate a sub-local namespace) quickly degrades into a recursive argument nightmare.
--- End quote ---

For those unfamiliar with NameSpace Push and Pop:
;---------------------------------------------------------------
NameSpace Push saves the current namespace as a temporary variable. Probably something like (pseudo-code) #pushed_nsname|type. All of a namespace's defined child !variables are stored within their parent namespace address, regardless of whether it was "pushed," or not.

NameSpace Pop sets the name space to the LAST "pushed," namespace AND can only be called once per push/pop (EUO seems to clear #pushed_nsname|type when pop is called).

If NameSpace Push is called multiple times before the cursor parses a NameSpace Pop, EUO will overwrite #pushed_nsname|type every time, destroying NameSpace Pop integrity.

As long as a sub maintains a 1:1 relationship, as in the called sub will only be called directly and does not call other subs, Push/Pop works fine.

Example of 1:1:

--- Code: easyuo ---;current namespace = default namespace = local stdbody:...gosub one_to_one...goto body sub one_to_one ;Sub One_To_One will only ever be called directly and never calls other subs.   namespace push ;Saves the current (local std) namespace, including                   ;   any defined !variables for recall with pop.   namespace local one_to_one ;Changes the current (local std) namespace to "local one_to_one."   ;Sub One_To_One Body.   ;Do Sub One_To_One things setting local !variables and referencing local !variables    ;   as well as setting script %variables to be passed to the script,    ;   and referencing script %variables previously defined.   ...   namespace clear ;Deletes all !variables for the current (local one_to_one) namespace.   namespace pop ;Changes the current (local one_to_one) namespace                  ;   back to the last_pushed (local std) namespace                 ;   and restores the stored !variables for it.return
But as soon as any directly called sub calls an/other sub(s), or a sub can be called directly and/or by an/other sub(s), or both/all (1:many || many:1 || many:many), push/pop integrity breaks down, and namespace integrity must be maintained manually. Luckily EUO also has #system_variables to handle this: #nsname and #nstype.
   *Note: There is more nuance to defining "many," but in the context of this thread,
              where I assume that all subs will populate a sub-local namespace,
              it is safe to assume my definitions above are correct.

My solution for this conundrum, for when I develop a new subroutine, is to assume that all subs will populate a sub-local namespace and have a many:many call relationship and manually store and delete #nsname and #nstype, and edit this out if I want to. Conversely I could assume this is not the case and add this in after the fact, but that doesn't change the solution.

Example solution for all relationship states (1:1 || 1:many || many:1 || many:many):

--- Code: easyuo ---sub many_to_many    set %many_to_many_nsname #nsname ;store the current #nsname and #nsntype    set %many_to_many_nstype #nstype ;before populating another namespace   namespace local many_to_many ;or whatever the sub is named   ;Do sub many_to_many things   ...   namespace clear   namespace %many_to_many_nstype %many_to_many_nsname    deletevar %many_to_many_nsname   deletevar %many_to_many_nstypereturn
This solution works the same as push/pop, except with several advantages:
   1. You don't have to know the final state of a sub's namespace relationship (n:n).
   2. It frees up push/pop for specified use elsewhere in your script/subs, if you prefer.
   3. You may ignore the current state of push/pop in publicly published subs.
   4. Each current namespace is permanently stored until all calls are returned.

The only disadvantage I can think of is that it costs 3 more lines/parse processes per potential push/pop, but that is immediately nullified when a potential push/pop push is overwritten.

Back to my original question, am I over-thinking this or is this a relevant solution?
In simpler terms, "Am I doing this right?" Or is there a better way?

Thanks for your time.

Gaderian:
Lines of code is fairly inconsequential for script speed. If your #LPC is 10 you do 10 lines in a time slice. If your LPC is 200, you do 200 lines in your timeslice. So with a moderate LPC having 3 lines of code makes a negligible difference.
So write code you need and adjust LPC later if needed.

I believe namespace push and pop can go many levels deep. I do not think you can reuse a namespace as unique, but enter the same namespace.
Use a systime based namespace name to be unique/or combine with random-if you need to. This would only be for very common used routines like a gump wait sub.

lydaan:
lol, thanks. you made me retest it... I didn't expect push/pop to be fully recursive (you know... EUO things and all). thanks for that. exactly what I was looking for. I overlooked something and solved a problem that didn't exist.

TrailMyx:
I never really thought too much into it.  Generally I abused the stack-style of management knowing that you needed a pop for every push.  I'd allow for persistent namespaces for data required locally throughout a script or globally between scripting instances.  So for that I might push/pop but not clear so that the data will be there the next time I entered that particular context.

The push/pop allows for pretty fast context switching, and can get you into trouble if you're not balancing your flow well (i.e. exiting a sub without poping).

So perhaps you might be overthinking it a bit just because pushing and popping are really just one intended method to switch context, and as you point out you can also directly access the NSNAME and NSTYPEs.

lydaan:

--- Quote ---Generally I abused the stack-style of management knowing that you needed a pop for every push
--- End quote ---

I just assumed it wasn't recursive, so I didn't test for it. Turns out EUO gets to be recursive, but your scripts can't. It makes a lot more sense now after Gaderian made me test for it.


--- Quote ---allow for persistent namespaces for data required locally throughout a script
--- End quote ---

I have something like this in a sub I'm designing, but am unsure as of yet if I will just copy variables or declare them in a unique namespace. need more testing to decide.


--- Quote ---perhaps you might be overthinking it a bit
--- End quote ---

At this point, definitely. I can think why you might need access to NSNAME and NSTYPE, and how you would use them, but have no idea when such complexity would be necessary.

Thanks for the reply. I was feeling like an idiot, now I realize I was just being foolish.

Navigation

[0] Message Index

[#] Next page

Go to full version