Page 1 of 1

super-global access from class static __new()

Posted: 30 Sep 2020, 12:33
by sirksel
A very large code base I maintain relies on certain "super-globals" that create "constants", on which nearly every function/method depends either directly or indirectly. For example:

Code: Select all

global na := '`vna'   ;sentry for missing parameter
Wherever na is used throughout thousands of functions/methods, none of these references ever use the global declaration because it's not required. They're super-globals! (As I've said in prior posts, it would be nice to be able to use these super-globals as parameter defaults too, but I've sort of given up on that one...)

So here's the problem... We know that static __new() for each class executes before any of the main body (autoexec) code, in the order classes are defined. Makes sense, except that some of my class initializers actually do stuff that requires other functions, so at least certain of the super-globals need to be set up first.

So I thought... no problem... since the class initializers execute in the order classes are defined, I'll just set up the super-globals in their own static class initializer which appears at the very top of the code. So I tried various incarnations of the following at the top of my code:

Code: Select all

class script_init {   ;class whose only purpose is the static __new()
  static __new() {
    global
    global na := '`vna'   ;sentry for missing parameter
  }
}
Of course, I quickly realized this doesn't create a super-global, since it's inside a function body. So I'm back to the drawing board. My options, as I currently perceive them, are:
  • rewrite all code to explicitly declare globals and never rely on super-globals (not a great option!)
  • don't do stuff that calls functions (that need super-globals) in class initializers (but I need to!)
  • fix just the functions called by class initializers to make explicit global declarations (introduces something that's not uniform across all functions though)
  • create routines in non-static (instance) __new that, on first run only, set up the required stuff I would have done in static __new... which required functions... which required super-globals... which have now already been defined... (but that seems like an ugly proxy for the actual purpose of static __new)
  • find some way to declare super-globals from a class initializer (...which is why I'm here asking for help) :D
Any thoughts would be much appreciated.

Re: super-global access from class static __new()

Posted: 30 Sep 2020, 12:51
by swagfag

Code: Select all

;sentry for missing parameter
if thats all ure using the variables for, its a crappy kludge - rewrite ur functions to make use of unset and IsSet()
otherwise

Code: Select all

global na ;sentry for missing parameter

class script_init {   ;class whose only purpose is the static __new()
  static __new() {
    na := '`vna'   ;sentry for missing parameter
  }
}

Re: super-global access from class static __new()

Posted: 30 Sep 2020, 13:20
by sirksel
Thanks for the quick answer. As usual, your answer worked like a charm!

#1:
Your example global na in the main body worked to allocate the super-global to be later set by the static __new of class script_init, but I'm confused... Does the global declaration in the main body actually execute before the class static __new methods? I also tried global na := '`vna' again, and it also works, but only to reserve the name as a super-global! It seems like the value-setting part of that statement is ignored at the time of the class static __new execution but then is somehow later executed??? I'm a little confused as to the order of things.

#2:
You're right that that's not the only reason I'm using the super-globals. It was just one example. However, on the topic you raise, the biggest reason I haven't rewritten with unset (aside from time) is that you can't pass it through to a successive function handler, as you can with a sentry. For example:

Code: Select all

specific_fn(v1:=unset) => general_fn(v1, 'x')
general_fn(v1:=unset, v2:=unset) => !isset(v1)
msgbox specific_fn()   ;0  (unset doesn't pass through)
versus with a sentry, you can pass it through:

Code: Select all

global na := '`vna'
specific_fn(v1:='`vna') => general_fn(v1, 'x')
general_fn(v1:='`vna', v2:='`vna') => v1 == na
msgbox specific_fn()   ;1  (sentry passes through)
I'm not sure if there's some way to pass through an unset as unset (without a bunch of conditionals), which is especially important in functions where there are a lot of combinations of optionals that might be set or unset. Any thoughts?

Re: super-global access from class static __new()

Posted: 30 Sep 2020, 23:22
by lexikos
Declarations are processed before the script executes. Variable initializers are just assignments, so are subject to control flow. The two parts are processed at different stages.

You can declare the variable outside the function, then assign it inside.

Re: super-global access from class static __new()  Topic is solved

Posted: 16 Oct 2020, 16:24
by swagfag
if there's some way to pass through an unset as unset
there is not. the way i understand it, the unset/IsSet combo isnt meant to be(come) a substitute for a nulltype