It Can Get Pretty Confusing When Considering Which AutoHotkey If Conditional to Use
Occasionally, when updating or modifying a script I run into a problem where an If conditional just stops working. At first, I experience the usual confusion, but, eventually, it occurs to me to enclose the subject of the conditional in parentheses. The code starts working again. How does this happen?
The Traditional If Statement Puzzle
The problem lies in the fact that the traditional AutoHotkey If statement uses a variable and a value, not an expression. That means that while the first term (the variable—referred to as Var in the online documentation) can represent any number or text, the second term (the Value) must appear as a constant—either a number or a text string. If we replace the constant with a variable, we must either convert it back into a constant with variable replacement (i.e. %variable%) or turn the entire operation into an expression.
- A variable (Var) contains or stores a value.
- A Value stands on its own as a constant without interpretation.
- An expression may contain multiple variables and/or values evaluated as a group.
Until recently, that limitation of the traditional If statement hadn’t sunk in with me. I often created lines of code such as:
Today := A_Now If A_WDay > 4 Today += 11-A_WDay, days Else Today += 4-A_WDay, days
This worked fine until I made it more flexible by replacing the constant 4 with the variable Day:
Day := 4 Today := A_Now If A_WDay >= Day ; Failed If statement Today += Day + 7 - A_WDay, days Else Today += Day-A_WDay, days
(As it happens, I could have turned the Day variable back into a value by using the macro replacement %Day%. Or, I could have forced the expression with a single percent sign: If % A_WDay >= Day.)
I make this type of mistake because of how I write scripts. I commonly start my code with a constant such as the 4 shown in the first snippet of code, then later change it to a variable such as Day in the second piece of code. I didn’t realize that I had changed a traditional AutoHotkey If statement into an If (expression) statement which requires parentheses:
Day := 4 Today := A_Now If (A_WDay >= Day) ; This works! Today += Day + 7 - A_WDay, days Else Today += Day-A_WDay, days
I not sure how many times in the past year I’ve struggled with an If statement which stopped working—only to discover that I needed to add the parentheses. Always using the If (expression) form of the conditional by default offers the best answer.
Traditional If Statements
In traditional If statements, AutoHotkey compares a variable to a value. They do not accept expressions. Therefore, you cannot compare one variable to another variable as in the code:
If A_WDay >= Day ; Fails!
which fails. Putting parentheses around the comparison turns it into an expression. Or, as an alternative, you can substitute the second variable with its value (%Var%):
If A_WDay >= %Day%
by surrounding it with percent signs.
However, best practice dictates using the If (expression) form of the code:
If (A_WDay >= Day)
Although in this situation, it would work, I avoid using the forced expression operator % in place of parentheses since it eventually disappears in the coming AutoHotkey V2.0. Plus, any of the other legacy If commands which use Var (e.g. IfEqual, IfInString, etc.) do not support forced expressions.
Deprecated V1.1 Commands
Many current AutoHotkey commands carry the label Deprecated. That means they disappear in AutoHotkey Version 2.0. However, I must emphasize that the powers-that-be have not yet issued a beta version of V2.0—much less a final release. Even then, moving to V2.0 remains your option as discussed in “AutoHotkey Version 2.0—Should I Wait for It?” However, I consider using the V2.0 supported alternatives found in V1.1 a best practice. Even if you never move to V2.0, the replacement commands and functions provide more flexibility and teach you better coding habits.
IfEqual, Var, Value (same: if Var = Value) IfNotEqual, Var, Value (same: if Var <> Value or if Var != Value) IfLess, Var, Value (same: if Var < Value) IfLessOrEqual, Var, Value (same: if Var <= Value) IfGreater, Var, Value (same: if Var > Value) IfGreaterOrEqual, Var, Value (same: if Var >= Value) If Var
However, AutoHotkey V2.0 removes all of these versions of If and a few other forms (below) which offer alternative functions that work in both V1.1 and V2.0. The online documentation recommends using the alternative function:
IfExist, FilePattern IfNotExist, FilePattern
Recommended alternative function FileExist().
IfInString, Var, SearchString IfNotInString, Var, SearchString
Recommended alternative function InStr().
IfWinActive , WinTitle, WinText, ExcludeTitle, ExcludeText IfWinNotActive , WinTitle, WinText, ExcludeTitle, ExcludeText
Recommended alternative function WinActive().
IfWinExist , WinTitle, WinText, ExcludeTitle, ExcludeText IfWinNotExist , WinTitle, WinText, ExcludeTitle, ExcludeText
Recommended alternative function WinExist().
Starting now, you should replace all of the above traditional If statements with If (expression)—using the parentheses—as your default. Those offering an alternative function use If (expression) with the function as follows:
Note: From If (expression) documentation, “the open-parenthesis may be omitted entirely if the first item after the word ‘if’ is a function call or an operator such as not or the ! [operator].”
Other forms of If found in V1.1 can cause consternation. From the online documentation:
Common cause of confusion: There are several other types of If statements, some of which look very similar to If (expression). These should be avoided in new scripts. If in doubt, it is best to always begin the expression with an open-parenthesis. The “legacy” If statements are as follows:
- If Var
- If Var op Value, where op is one of the following operators:
- If Var [not] between Lower and Upper
- If Var [not] in/contains MatchList
- If Var is [not] Type
Any If statement which does not match one of the usages shown above is interpreted as If (expression).
Now that I comprehend how traditional If statements work with variables and values, I see why those other forms of the If statement deprecate in AutoHotkey V2.0—including those above—in favor of If (expression). (Note: You can use InStr() function to replace the MatchList statement form and the Value is Type expression operates in V2.0.)
The Bottom Line: Avoid the multitude of traditional If statements in AutoHotkey V1.1 and use the If (expression) form of the statement.
This post was proofread by Grammarly
(Any other mistakes are all mine.)
(Full disclosure: If you sign up for a free Grammarly account, I get 20¢. I use the spelling/grammar checking service all the time, but, then again, I write a lot more than most people. I recommend Grammarly because it works and it’s free.)