Difference in existing variables in "Switch" and "If Then"

Hello,

The complete execution of one of my macros depends on the existence of a specific (global) variable. Unfortunately, there is a problem and the macro is not running as intended. So I tried to test the existence of the variable by deleting it via the "Set Variable to Text"-action (%Delete%) and triggering a notification if the condition "If variable "RandomName" exists" is met.
Strangely enough, the result differs between using a "Switch" or an "If Then"-action.
The "Switch" triggers the notification when I set the condition to "If variable "RandomName" exists" and the "If Then"-action triggers the notification when the condition is set to "If variable "RandomName" does not exist".
I prefer to use a "Switch" to streamline my macros, but in this case it is breaking its function.

Can you help me to understand why this is happening?

Occasionally a question is so good that I'm floored. Yours is one such question. Let me paste some actions to illustrate your problem.

I've create a couple of testing macros. This loop checks if a global variable called "Global" exists or not. If it exists, it "speaks" that it exists, then deletes the variable. In this loop, the variable will be created and deleted twice each. And it works fine.

image

The following should do the exact same thing, but fails, as the variable always seems to "exist."

image

I think I agree with you, the Switch action (the "exists" condition) is not working properly. My only theory is that it is a bug in the Engine. Specifically, the "exists" condition always returns "true" for any variable provided, regardless of whether it exists or not.

Furthermore, the "does not exist" condition always returns "false" regardless of whether the variable exists. This is a distinct, different issue.

I found a workaround. You could do this in the meantime. This does exactly what you want.

image

1 Like

@Airy, thanks for the response and the time you invested.

I also tried the last approach with the "Text"-parameter when trying to solve the "issue". Using it didn't work in my scenario, because at the end of the loop I reset the variable to the empty string. It being empty but existing is a condition I "need" in my setup. This may not be optimal, but it works in coherence with all the other macros and actions depending on this variable.

Meanwhile, I was able to remove the variable from the macro I described. It's simpler and works even better now. After experimenting unsuccessfully for quite some time and not understanding the different behavior between "Switch" and "If Then" in this case I turned to the forum. It's guaranteed to get a solution for a problem or at least having an interesting conversation here.

I still would like to know why the two actions behave differently.

I have run some quick tests and agree with @Airy's findings. Page loading in the forum is impossibly slow for me today (an unusual but not unprecedented problem) and also I am short of time – but I'll mention the following just in case they might contain some clues, and wish you luck! :+1:

As you can see below, (only the third test condition passes) there is no difference in the results of an "exists test" between an empty string and the string "%Delete%" regarding whether a variable is empty. So how exactly are you testing whether a variable exists when this code proves there is no difference?

image

An empty string and a string that was assigned "%Delete%" are both non-existent in terms of KM's test.

So how exactly are you getting KM to say otherwise? My code proves that there is no difference.

From the man himself, in another thread:

...and it appears that "Switch/Case" and "If Then" ask in different ways and get different answers.

As Peter said in that thread and @Airy showed above, it's better to use "is/is not empty" -- whether a variable has been %delete%ed, set to an empty string, or has never been instantiated, it "is empty" for both "Switch/Case" and "If Then" actions.

Can you explain this? There may be other ways to do what you want -- or there's always the "explicitly set to a known bogus value" method, just as easy to test for as "exists".

1 Like

In that case (no pun intended!):

  • Checking whether a variable exists deserves an Action Warning in the editor (if technically possible, @peternlewis!)
  • This is another reason to add exists and not exists to the list of conditions for switch and if/then in the Wiki – and with a mention of this issue.

Then change the behaviour of your macro.

Base your decision on the value of the variable, or on some other variable’s value.

The question of whether a variable exists does not make sense to ask.

The If Then Else and Switch different in this behaviour because the If Then Else is testing based on the actual variable, while the Switch is testing based on the contents of the variable.

And you're right, it doesn't make sense to allow testing for existence of a variable when it has no good meaning, so I will remove it for the next version.

Why? How did you get to the point of needing to distinguish this case?

3 Likes

I wonder if we don't tend, out of habit, to speak of "a variable" a bit foggily ?

When a name is bound to a value (in some specific name-space) it's tempting to think of that relationship (with a bit of hand-waving) as "a variable" but there will always be two entirely separate questions:

  1. Does the name-space contain that name ?
  2. What value (if any) is bound to that name ?

Except in a “language” like Keyboard Maestro where variables are created or deleted on the fly, any variable name has a value (being “” by default) which is why “existence” does not really make sense and I should never have included it.

6 Likes

@Airy You are absolutely right, and using the Text-parameter works as intended in this case. I replied to you before giving this idea another go and testing it thoroughly, which is never a good idea. My bad.
It is likely that something else was causing a problem and thus giving me a different result when I was trying to solve the issue. I have updated my macro and everything works great now.
Thank you for leading me to the right direction.

1 Like

I thought using "Set variable to Text" and leaving it blank would be necessary before using the "empty"-condition in a Switch or If Then Else. It didn't occur to me that a variable doesn't need to be in the variable list for it to be usable in an action.
Variables are a fascinating topic to me, and I learn something new each time I'm experimenting with them. I updated a few macros and everything works as intended.

1 Like

I've done so and thank you for clearing this up for me.
I guess I got a little carried away after finding out about variables and their potential and used them inflationary. This was a good opportunity to simplify and optimize a few macros.

Interesting. This knowledge might come in handy in the future. Thanks again.

1 Like