Check if variable exists without querying its contents

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Sam_
Posts: 146
Joined: 20 Mar 2014, 20:24

Check if variable exists without querying its contents

Post by Sam_ » 02 Jun 2020, 12:33

Is there a way to check if a variable has been defined without querying its contents? I'm looking for a IsVariable(), somewhat analogous to IsObject(), IsFunc(), or Object.HasKey().

What I want to avoid is doing something like

Code: Select all

#Warn All, StdOut  ; Enable warnings to assist with detecting common errors.
If NOT var
	var:="bla"
Which gives the warning "Warning: This variable has not been assigned a value."
Note that I am not interested in turning off all such warnings.

TIA

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Check if variable exists without querying its contents

Post by Helgef » 02 Jun 2020, 13:19

Do you mean that you want to check if a variable has been assigned a value without triggering a warning if it hasn't? V2 has isSet for that, I don't think it was added to v1, in which case there is no way to do that in v1.

Variables exist simply by being written anywhere in the script.

Cheers.

Sam_
Posts: 146
Joined: 20 Mar 2014, 20:24

Re: Check if variable exists without querying its contents

Post by Sam_ » 02 Jun 2020, 13:49

Helgef wrote:
02 Jun 2020, 13:19
Do you mean that you want to check if a variable has been assigned a value without triggering a warning if it hasn't?
Yes, exactly this.
Helgef wrote:
02 Jun 2020, 13:19
V2 has isSet for that, I don't think it was added to v1, in which case there is no way to do that in v1.
That is exactly what I'm looking for, but yes I meant for v1. Would it be possible/reasonable to silently query the variables list from the script's main window?

Sam_
Posts: 146
Joined: 20 Mar 2014, 20:24

Re: Check if variable exists without querying its contents

Post by Sam_ » 02 Jun 2020, 16:32

Sam_ wrote:
02 Jun 2020, 13:49
Would it be possible/reasonable to silently query the variables list from the script's main window?
Not elegant, but a proof of concept:

Code: Select all

#Warn All, StdOut  ; Enable warnings to assist with detecting common errors.

; Check a variable that does not exist, and display the text we're checking against
MsgBox % IsVar("notavar",1)
; Check a variable that does exist
MsgBox % IsVar("A_Args")

; Check if variable exists without displaying a warning (it doesn't)
If !IsVar("notavar")
	var:="bla"

ExitApp


IsVar(__var_,__DisplayText_:=0){
	DetectHiddenWindows, On
	WinMenuSelectItem, ahk_id %A_ScriptHwnd%, , View , 2&
	WinHide, ahk_id %A_ScriptHwnd%
	WinGetText, __varlist_, ahk_id %A_ScriptHwnd% ;ahk_class Edit1
	WinHide, ahk_id %A_ScriptHwnd%
	If InStr(__varlist_,"`n" __var_ "[") OR InStr(__varlist_,"`n" __var_ ": Object")
		Return 1
	If __DisplayText_
		MsgBox %__varlist_%
	Return 0
}


Sam_
Posts: 146
Joined: 20 Mar 2014, 20:24

Re: Check if variable exists without querying its contents

Post by Sam_ » 02 Jun 2020, 17:15

gregster wrote:
02 Jun 2020, 16:47
Perhaps this helps: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=9656
I forgot about that function, thanks. It makes getting the list of global variables easier. I guess I'd still have to do something inline to get the local variables.

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 23 Jan 2022, 18:52

Code: Select all

abc := "Var for abc"
test := "abc"
if isVar(test)
msgbox % """" test """ is a variable & its value is """ isVar(test) """"
else
msgbox variable not found

isVar(testVar){
try
testVar := %testVar%
catch
testVar := 0
return testVar
}

iPhilip
Posts: 815
Joined: 02 Oct 2013, 12:21

Re: Check if variable exists without querying its contents

Post by iPhilip » 23 Jan 2022, 20:22

icc2icc wrote:
23 Jan 2022, 18:52

Code: Select all

abc := "Var for abc"
test := "abc"
if isVar(test)
msgbox % """" test """ is a variable & its value is """ isVar(test) """"
else
msgbox variable not found

isVar(testVar){
try
testVar := %testVar%
catch
testVar := 0
return testVar
}
That doesn't quite do it. First of all, the isVar function can be simplified as (the catch block never gets called):

Code: Select all

isVar(testVar) {
   return %testVar% ? true : false  ; Relies on the dynamic variable reference resolving to an existing global variable because no local variable exists by that name.
}
The reliance on an existing global variable means that this works:

Code: Select all

abc := "Var for abc"
test := "abc"
if isVar(test)
   msgbox % """" test """ is a variable & its value is """ %test% """"
else
   msgbox variable not found

isVar(testVar) {
   return %testVar% ? true : false  ; Relies on the dynamic variable reference resolving to an existing global variable because no local variable exists by that name.
}
but this doesn't:

Code: Select all

foo(3)

foo(x) {
   msgbox % isVar(x) ? "The x variable is set" : "The x variable is not set"
}

isVar(testVar){
   return %testVar% ? true : false  ; Relies on the dynamic variable reference resolving to an existing global variable because no local variable exists by that name.
}
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 26 Jan 2022, 23:20

you are right, I missed that
& actually I just realized that it didn't solve at all the issue with #warn
but as per your comment about local variables I do have another idea

How about this one?
Slightly edited

Code: Select all

test1 := 0  ; The variable was set to the value of zero
test2 = ""  ; The variable was set to the value of ""

if isVar(test1)
	msgbox % "[test1] is a variable & its value is [" test1 "]"
if isVar(test2)
	msgbox % "[test2] is a variable & its value is [" test2 "]"
isVar(testVar := ""){
	return (testVar <> "") 
}
Last edited by icc2icc on 02 Feb 2022, 13:36, edited 3 times in total.

iPhilip
Posts: 815
Joined: 02 Oct 2013, 12:21

Re: Check if variable exists without querying its contents

Post by iPhilip » 27 Jan 2022, 12:22

@icc2icc, that's closer but your new function basically tests if a variable is not null, not if it hasn't been set. Here's a simple test where your new function fails.

Code: Select all

test := 0  ; The variable test was set to the value of zero
if isVar(test)
	msgbox % """" test """ is a variable & its value is """ %test% """"
if !isVar(notVar)
	msgbox variable not found

isVar(test := False){
return test
}
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 27 Jan 2022, 14:37

iPhilip wrote:
27 Jan 2022, 12:22
@icc2icc, that's closer but your new function basically tests if a variable is not null, not if it hasn't been set. Here's a simple test where your new function fails.
I edited my code to fix this

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 31 Jan 2022, 18:45

just to finish up about #warn when checking unset variable
if you had declared the variable even if its empty you won't get that warning
put var= on top of the script

iPhilip
Posts: 815
Joined: 02 Oct 2013, 12:21

Re: Check if variable exists without querying its contents

Post by iPhilip » 31 Jan 2022, 22:39

icc2icc wrote:
27 Jan 2022, 14:37
I edited my code to fix this
In my opinion you didn't. In your earlier slightly edited post, you wrote:

Code: Select all

test2 = ""  ; The variable was set to the value of ""
Because you initialized test2 with the = operator (instead of the := operator - a common error), test2's value is not a blank but two double-quotes. Your statement is equivalent to

Code: Select all

test2 := """"  ; The variable was set to two double-quotes
When you change that to what I think you intended

Code: Select all

test2 := ""  ; The variable was set to a blank
your function will return false, indicating that test2 has not been set.

Helgef's earlier statement is correct and worthy of consideration:
Helgef wrote:
02 Jun 2020, 13:19
Variables exist simply by being written anywhere in the script.
What this means is that, at least in AHK v1, by its very existence in a script, a variable is initially set to a blank. The documentation supports that statement:
https://www.autohotkey.com/docs/Concepts.htm#uninitialised-variables wrote: Although the program automatically initializes all variables (an empty string being the default value), ...
Thus,

Code: Select all

test1 := ""
MsgBox % isVar(test1) " = " isVar(test2)  ; test1 was explicitly set while test2 was automatically set.
In AHK v2, variables are not automatically initialized. Thus, the function isSet makes sense.

I hope this helps.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

User avatar
boiler
Posts: 16915
Joined: 21 Dec 2014, 02:44

Re: Check if variable exists without querying its contents

Post by boiler » 31 Jan 2022, 23:36

iPhilip wrote: Because you initialized test2 with the = operator (instead of the := operator - a common error), test2's value is not a blank but two double-quotes. Your statement is equivalent to

Code: Select all

test2 := """"  ; The variable was set to two double-quotes
A minor point, but just so there's no confusion, the above expression assignment sets the variable to contain one double-quote because each pair of double-quotes inside the quoted string is a single double-quote (because the first one escapes the second one). The following sets it to two:

Code: Select all

test2 := """"""

iPhilip
Posts: 815
Joined: 02 Oct 2013, 12:21

Re: Check if variable exists without querying its contents

Post by iPhilip » 01 Feb 2022, 11:29

@boiler, Thank you for catching that! :)
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 02 Feb 2022, 13:40

@iPhilip you are correct I will not compare it to isSet but what I tried to accomplish is to check if a variable has any value in it, (equals to if (var <> "") just fancier)
because this is usually what people want to check if the variable already got any value, & they don't care if the variable was declared, but if they do care there is no solution in v1

(& yes I did intentionally write test2 = "" because I wanted to set it to 2 double quotes so it should have a value just to demonstrate that it works, other then the
isVar(test := False){
return test
}

that didn't catch that & returned false)

iPhilip
Posts: 815
Joined: 02 Oct 2013, 12:21

Re: Check if variable exists without querying its contents

Post by iPhilip » 02 Feb 2022, 15:05

... so then perhaps the function should be renamed as:

Code: Select all

isVarEmpty(Var){
   return Var = ""
}
since isVar in my opinion is a misnomer (all variables names represent a variable - ;)). Also, it's not clear why you have a default value for the input parameter (isVar(testVar := "")). I would not expect anyone to use it without an input parameter, i.e. isVar() . Finally, note that the <> operator has been deprecated. The documentation encourages the use of != in its place.

Personally speaking, I have no use for such a function. I rely on the #Warn messages to tell me if I forgot to set a variable.

With respect to the original post:
Sam_ wrote:
02 Jun 2020, 12:33
Is there a way to check if a variable has been defined without querying its contents?
Yes, but only in AHK v2 via the isSet function.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

icc2icc
Posts: 18
Joined: 04 Aug 2021, 21:24

Re: Check if variable exists without querying its contents

Post by icc2icc » 06 Feb 2022, 14:03

With respect to the original post:
you are right, I missed the word defined
it's not clear why you have a default value for the input parameter
Because if you send isVar(test) when test was never defined, then its equals to isVar()

Post Reply

Return to “Ask for Help (v1)”