VarIsInit/VarExist or static for global variables
Posted: 04 Feb 2019, 15:26
Introduction
- IsInit(var)/VarIsInit(var): check if a variable has a value (without triggering #Warn).
- Perhaps: report 2(/A/B) for built-in variables.
- VarExist(VarNameAsStr): check if a variable exists.
- In simple terms: check if a variable is in ListVars.
- More specifically: check if a variable appears explicitly in the script (or if a variable with that name has been created dynamically at runtime).
- Note: a variable can exist, but have no value.
- E.g. Sleep, % var, var may never be given a value, but due to its presence in the script, it 'exists', and so appears in ListVars.
Rationale for IsInit/VarIsInit
- With a script like this, and with #Warn mode on, you get a classic problem:
Warning: This variable has not been assigned a value.
- Here's a more complex example:
- The current best solution is to anticipate all of those global variables and define them as blank or 0 in the auto-execute section.
- The best solution might be an IsInit/VarIsInit/IsNull function, which should *not* trigger #Warn.
- Another possible solution is to wrap everything as functions (and use 'static' in the function's local namespace).
- Another solution could be to allow 'static' (or equivalent) in the global namespace. That way you can keep the variable initialisation and the code proper together. (Versus have the variable initialisation moved to the auto-execute section.)
- ... (Perhaps static var := "" for the same variable could be allowed multiple times, but only the last (or first) one would be stored, before the script starts.)
- Or perhaps there is another solution or keyword that might be appropriate, e.g. 'execute a line once only', the first time you see it, but never again.
- [EDIT:] Btw 'try' does not work as a solution for this, this raises an error:
Rationale for VarExist
- E.g. an object may contain 1000 constants, 10 of those appear in the script, as variables with no values, and so you could check for each constant whether a variable existed, and assign values to those 10 variables, rather than create 1000 variables.
- E.g. for use for with WM (window message) constants or xl (MS Excel) constants.
- It also means that if you check ListVars, it usefully lists only the constants that are *used* by the script, rather than cluttered with every possible constant.
- Thanks for reading. Please notify of any similar threads.
- IsInit(var)/VarIsInit(var): check if a variable has a value (without triggering #Warn).
- Perhaps: report 2(/A/B) for built-in variables.
- VarExist(VarNameAsStr): check if a variable exists.
- In simple terms: check if a variable is in ListVars.
- More specifically: check if a variable appears explicitly in the script (or if a variable with that name has been created dynamically at runtime).
- Note: a variable can exist, but have no value.
- E.g. Sleep, % var, var may never be given a value, but due to its presence in the script, it 'exists', and so appears in ListVars.
Rationale for IsInit/VarIsInit
- With a script like this, and with #Warn mode on, you get a classic problem:
Warning: This variable has not been assigned a value.
Code: Select all
#Warn
q:: ;increment value
if (var = "")
var := 0
var++
MsgBox, % var
return
/*
;ideal solution:
q:: ;increment value
if !IsInit(var)
var := 0
var++
MsgBox, % var
return
;ideal solution (refactored):
q:: ;increment value
var := IsInit(var) ? var+1 : 1
MsgBox, % var
return
;a workaround: use a function and a static variable:
q:: ;increment value
MsgBoxAndIncValue()
return
MsgBoxAndIncValue()
{
static var := 0
var++
MsgBox, % var
}
*/
- Here's a more complex example:
Code: Select all
#Warn
q:: ;replace text in selected text
;static vGblBefore := ""
;static vGblAfter := ""
Clipboard := ""
SendInput, ^c
ClipWait, 3
if ErrorLevel
{
MsgBox, % "error: failed to retrieve clipboard text"
return
}
vText := Clipboard
InputBox, vGblBefore,, before:,,,,,,,, % vGblBefore
InputBox, vGblAfter,, after:,,,,,,,, % vGblAfter
vText := StrReplace(vText, vGblBefore, vGblAfter)
Clipboard := vText
SendInput, ^v
return
- The best solution might be an IsInit/VarIsInit/IsNull function, which should *not* trigger #Warn.
- Another possible solution is to wrap everything as functions (and use 'static' in the function's local namespace).
- Another solution could be to allow 'static' (or equivalent) in the global namespace. That way you can keep the variable initialisation and the code proper together. (Versus have the variable initialisation moved to the auto-execute section.)
- ... (Perhaps static var := "" for the same variable could be allowed multiple times, but only the last (or first) one would be stored, before the script starts.)
- Or perhaps there is another solution or keyword that might be appropriate, e.g. 'execute a line once only', the first time you see it, but never again.
- [EDIT:] Btw 'try' does not work as a solution for this, this raises an error:
Code: Select all
#Warn
try Var := VarWithNoValue
Rationale for VarExist
- E.g. an object may contain 1000 constants, 10 of those appear in the script, as variables with no values, and so you could check for each constant whether a variable existed, and assign values to those 10 variables, rather than create 1000 variables.
- E.g. for use for with WM (window message) constants or xl (MS Excel) constants.
- It also means that if you check ListVars, it usefully lists only the constants that are *used* by the script, rather than cluttered with every possible constant.
- Thanks for reading. Please notify of any similar threads.