Initialising global numeric fields

Assume I have a GLOBAL variable called ErrorCount.
In a number of different macros i have
ErrorCount := ErrorCount +1
If ErrorCount > 10 then give up....

These statements fail if ErrorCount does not have a numeric "value"

So I have a separate macro that is triggered at Login and Engine Launch that initialises ErrorCount to zero

That works fine.

Is there a neater way to do this? and embed the initialisation in the main macro
eg

If (ErrorCount is not numeric) then
set ErrorCount to zero.
ErrorCount := ErrorCount +1 should work fine

But there does not appear to be a numeric test.

Any suggestions
e.g. regex test for numeric? (should allow for +ve and -ve integers)

Start by finding out why a persistent shared variable that should be a number keeps getting either deleted or set to not-a-number. If it isn't reliably what it should be (after first initialisation, obvs) then that's a problem...

Otherwise, "Try/Catch" is one solution:

image

Other ways have been posted, but they're for "a variable may not exist" and it sounds like you also want to cater for "exists, but isn't a number".

1 Like

OK that would work. I have never used Try/Catch before.
Out of interest, does anyone know what value a global variable has before it is initialised? is space? null?

You can test for whether the variable is empty (it is).

Edit: but it will also be if you set it to an empty string… so this won't be useful in every case!

image

It doesn't -- unlike many other languages, there's no "declaration" of variables before assignment (well, there probably is, under the hood and internal to the action -- but that's not our problem as there's nothing we can do about it!).

Consider the following, where you might think of the first action as a variable declaration:

image

That'll throw an error "Can't get variable Global_neverUsedVar3" -- put anything into the "to" filed of the first action and the AS works as expected. Delete everything from the "to" field, run again, and you'll get the error -- our persistent global no longer exists because it has no value assigned.

Edit to add:

Luckily, as @kevinb shows above, the "is empty" condition also includes "doesn't exist". So yes, you can successfully "is empty" test a variable then have the AS fail :wink:

image

Have a play with this:

Emptiness....kmmacros (6.1 KB)

2 Likes

Those are pseudocode statements. Pseudocode can never be executed and can never fail. Your pseudocode has more than one way to implement in KM actions, and some of those ways could fail, but some will not.

That's unnecessary. If you choose the right way to implement the pseudocode above, you don't need to initialize ErrorCount. For example, here's one way to add "1" to a variable that will NOT fail if that variable does not have a numeric value:

image

Of course, Nige's solution is good, and I use his method occasionally, but I also use the above method occasionally, which is terser (and in my opinion, clearer.)

I went for "Try/Catch" over this because it wasn't clear from the OP what "does not have a numeric value" means, and "numeric test" implies that the variable might be non-empty and not a number.

If it can be guaranteed that the variable is either a number or empty/non-existent then yes, I think your method is better.

1 Like

Not pseudo code but a nod to dim and distant Algol60 :slight_smile:

CALCULATE(%Variable%ErrorCount%) + 1
and
CALCULATE(0%Variable%ErrorCount%) + 1
work under various conditions e.g. not declared/not yet used/ null / numeric value
but
do not work if ErrorCount holds a string e.g. "this is a string"

In practice, it would cover the case where ErrorCount is undeclared, and hopefully my code would NOT assign a string to a "numeric field".

So either Nige_S' or Airy's solution would work.

The 0 (zero) in the CALCULATE appears to be necessary.

The zero is what makes it work. Breaking it down...

The CALCULATE() function lets you use text tokens in a numeric field -- the stuff between the parentheses is text. So you're taking the string "0" and concatenating with the string evaluated by the token %Variable%ErrorCount% -- if ErrorCount holds 1, 3, or 1001 you'll get "01", "03", or "01001".

But if ErrorCount is empty the text token evaluates to an empty string, "", and the result of the concatenation is "0". Compare that with when you treat it as a number in a numeric field -- the evaluation errors. And that's the trick here.

Now CALCULATE() evaluates your string as a numeric expression. CALCULATE("01") evaluates to 1, "03" to 3, "01001" to 1001 -- and CALCULATE("0") is 0. And you now have a number that you can add 1 to.

Don't hope -- make sure. I'll reiterate this point:

If, for some reason, you can't stop it being set to something other than a number then you'll have to either always "Try/Catch" or put up with the occasional errored execution -- because you're using a global it could get changed in the background mid-execution, so a single test at the start of the macro won't be enough.