VarIsInit/VarExist or static for global variables

Propose new features and changes
User avatar
jeeswg
Posts: 6714
Joined: 19 Dec 2016, 01:58
Location: UK

VarIsInit/VarExist or static for global variables

04 Feb 2019, 15:26

- 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

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 current best solution is to anticipate all of those global variables and define them as blank or 0 in the auto-execute section.
- 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' in the global namespace. That way you can keep the variable creation and the code proper together. (Perhaps static var := "" for the same variable could be allowed multiple times, but only the first one would be executed, before the script starts.)
- Another solution might be a VarIsInit/VarExist/IsNull function, which should *not* trigger #Warn.
- 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.
- Thanks for reading. Please notify of any similar threads.

- [EDIT:] Btw 'try' does not work as a solution for this, this raises an error:

Code: Select all

#Warn
try var := nonvar
[EDIT:] Added mentions of VarIsInit.
Last edited by jeeswg on 11 Jun 2019, 14:08, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6714
Joined: 19 Dec 2016, 01:58
Location: UK

Re: VarExist or static for global variables

09 Jun 2019, 09:10

It turns out that the 1-parameter mode of VarSetCapacity is a sufficient solution, it reports 0 if the variable is empty or non-existent. That said, it would still be beneficial to have a VarIsInit(/VarExist) function.

VarSetCapacity can be used as a pseudo-VarIsInit function, for the example above, adding in these lines before the InputBox works to avoid a #Warn error:

Code: Select all

vGblBefore := VarSetCapacity(vGblBefore) ? vGblBefore : ""
vGblAfter := VarSetCapacity(vGblAfter) ? vGblAfter : ""
Here is an additional example:

Code: Select all

#Warn

q:: ;toggle - test VarSetCapacity as a pseudo-VarIsInit
if !VarSetCapacity(var)
	var := 1
else
	var := !var
MsgBox, % var
return

w:: ;toggle - test VarSetCapacity as a pseudo-VarIsInit one-liner
var := VarSetCapacity(var) ? !var : 1
MsgBox, % var
return

e:: ;toggle - test without VarSetCapacity (error message the first time, if #Warn on)
if !var2
	var2 := 1
else
	var2 := !var2
MsgBox, % var2
return
[EDIT:] Replaced VarExist with VarIsInit.
Last edited by jeeswg on 11 Jun 2019, 14:06, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4252
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: VarExist or static for global variables

09 Jun 2019, 10:00

Code: Select all

a := {}
c := ""
VarSetCapacity(c, 0)
d := 0 + 0
e := 0
Msgbox % VarSetCapacity(a)
Msgbox % VarSetCapacity(b)
Msgbox % VarSetCapacity(c)
Msgbox % VarSetCapacity(d)
Msgbox % VarSetCapacity(e)
VarSetCapacity measures the size of the internal string buffer is the exact description.
It has no use as a VarExists function.
Recommends AHK Studio
Helgef
Posts: 3924
Joined: 17 Jul 2016, 01:02
Contact:

Re: VarExist or static for global variables

09 Jun 2019, 10:35

[edit:]a quote to clarify,
functions wrote:Any non-dynamic reference to a variable creates that variable the moment the script launches
[end edit]
Concepts/Variables wrote:In AutoHotkey, variables are created simply by using them
You probably want to ask for a isVarInitialised function. An actual varExist function would take a string as input. If you want a varExist function which takes a variable as input, here you go,

Code: Select all

jee_varexist(byref var){
	if isbyref(var)
		return true
	throw ; invalid use
}
I don't think we should add any means to facilitate the use of bad practice.
Another solution could be to allow 'static' in the global namespace. That way you can keep the variable creation and the code proper together.
Again, you mean var initialisation, not creation. lexikos already suggested auto expr and / or auto { ... } :arrow: here , that seems more generally useful.

Also, in addition to nnnik's examples, consider that a local variable might be uninitialised but still have a capacity greater than zero from an earlier instance of the function. For example,

Code: Select all

#warn
f()
f()
f(){
	if !VarSetCapacity(var)
		var := 1
	else
		var := !var
	MsgBox, % var
	return
}
Cheers.
Last edited by Helgef on 09 Jun 2019, 12:23, edited 1 time in total.
User avatar
jeeswg
Posts: 6714
Joined: 19 Dec 2016, 01:58
Location: UK

Re: VarExist or static for global variables

09 Jun 2019, 11:48

- @nnnik: My main use for a VarExist/VarIsInit function, is fulfilled by VarSetCapacity:
- 'VarSetCapacity can be used as a pseudo-VarExist function', 'it reports 0 if the variable is empty or non-existent'.
- Note: 'pseudo-', no claim was made that it was equivalent to VarExist/VarIsInit.

- @Helgef: That quote, 'by using them', is actually ambiguous. E.g. does var := MyUninitialisedVar, with #Warn on, create 2 variables prior to or during execution. Since they appear in ListVars, this suggests prior.

Code: Select all

#Warn
ListVars
MsgBox
var := MyUninitialisedVar
- What are your definitions. A variable in ListVars = created? A variable that causes a #Warn error when read = not initialised?
- Hmm. Perhaps you'd have in mind: VarIsInit(var) and VarExist("varname") (because for VarExist(var), the presence of var in the script, in the VarExist line, would make it exist. Both functions would be useful, in simple terms, VarExist could be created via VarIsInit, handling scope would make the functions more complicated.
- (Is your varexist function an (reasonably successful) attempt at humour? It creates the variable if it doesn't exist, and thus always returns true.)
- Some tests:

Code: Select all

;test VarSetCapacity (tested on AHK Unicode)

a := {}
;b (no variable defined)
c := ""
VarSetCapacity(c, 0)
d := 0 + 0
e := 0
f := 0
f := 0 + 0
g := 1
g := !g
h := false ? 1 : 0
i := false ? 1 : !1
j := "0"
k := "abc"
l := "abcd"

MsgBox(VarSetCapacity(a)) ;AHK v1/v2: 0
MsgBox(VarSetCapacity(b)) ;AHK v1/v2: 0
MsgBox(VarSetCapacity(c)) ;AHK v1/v2: 0
MsgBox(VarSetCapacity(d)) ;AHK v1: 0, AHK v2: 6
MsgBox(VarSetCapacity(e)) ;AHK v1/v2: 6
MsgBox(VarSetCapacity(f)) ;AHK v1/v2: 6
MsgBox(VarSetCapacity(g)) ;AHK v1: 0, AHK v2: 6
MsgBox(VarSetCapacity(h)) ;AHK v1/v2: 6
MsgBox(VarSetCapacity(i)) ;AHK v1: 0, AHK v2: 6
MsgBox(VarSetCapacity(j)) ;AHK v1/v2: 6
MsgBox(VarSetCapacity(k)) ;AHK v1/v2: 6
MsgBox(VarSetCapacity(l)) ;AHK v1/v2: 14

Code: Select all

;test varexist

a := {}
c := ""
VarSetCapacity(c, 0)
d := 0 + 0
e := 0
f := 0
f := 0 + 0

MsgBox(varexist(a)) ;AHK v1/v2: 1
MsgBox(varexist(b)) ;AHK v1/v2: 1
MsgBox(varexist(c)) ;AHK v1/v2: 1
MsgBox(varexist(d)) ;AHK v1/v2: 1
MsgBox(varexist(e)) ;AHK v1/v2: 1
MsgBox(varexist(f)) ;AHK v1/v2: 1
;MsgBox(varexist("abc")) ;AHK v1/v2: error

varexist(byref var){
	if isbyref(var)
		return true
	throw ; invalid use
}
- @Helgef: Do you have any further details re. your 'f()' example, it's quite counterintuitive. It's a great example, thanks for sharing.

- @nnnik/@Helgef: As in other threads, you may think you have clarified the situation, but you have also made some things less clear.
- (If I was take your attitude in previous threads, I could make the case that you've just spread misinformation. To take my attitude, I'd say that you've stated some useful information, and that being 100% clear and accurate can be difficult even for basic information.)
- (I'd also state that you're welcome to add [EDIT:] marks to your posts, to add greater clarity, and that you're welcome to suggest improvements to my posts (but only if you are extremely clear in your suggestions, to avoid me asking you to clarify the suggestions in a prolonged back and forth).)
Last edited by jeeswg on 20 Jun 2019, 22:39, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6714
Joined: 19 Dec 2016, 01:58
Location: UK

Re: VarExist or static for global variables

10 Jun 2019, 23:29

I wrote some C++ code for a potential VarIsInit function, here:
C++: AHK source code: VarIsInit - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=65308
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 12 guests