AutoHotKeyスクリプトにおけるグローバル変数とローカル変数
With the exception of local variables in functions, all variables are global; that is, their contents may be read or altered by any part of the script. Except where noted on the functions page, variables do not need to be declared; they come into existence simply by using them (and each variable starts off empty/blank).
(Google翻訳)
関数のローカル変数を除いて、すべての変数はグローバルです。 つまり、その内容はスクリプトの任意の部分によって読み取られたり変更されたりする可能性があります。 関数ページに記載されている場合を除いて、変数は宣言する必要はありません。 それらを使用することによってそれらが存在するようになります(そして、各変数は空白/空白で始まります)。
これを読むと、「関数内でローカルに格納された変数は、関数外から参照できない」ということはもうそのまんまわかる。
AutoHotKeyスクリプトにおいて、「ローカル変数」というのは関数ローカルという意味でしかない。スレッドローカルとか、サブルーチンローカルとか、ラベルローカルとか、そんなもんはない。
関数以外で格納された全ての変数と、関数内でglobal
として宣言された変数は、グローバル変数である。つまり、スクリプト内のどこからでも参照できるはずである。
では、「関数外でグローバルに格納された変数は、関数内から参照できるのか」。できそうに思える。
関数からグローバル変数を参照する
ところがぎっちょん。
以下のスクリプトでは、普通にMsgBox
した時にローカル変数LVar
が空なのは当然として、関数TestFunc
からMsgBox
した時、グローバル変数GVar
は空になる。
GVar = hoge ; グローバル変数GVarをつくる
MsgBox, , %A_ScriptName%, This is plain command`nGvar = %GVar%`nLVar = %LVar%
; LVarは空
TestFunc()
; GVarは空
Exit
TestFunc() {
LVar = fuga ; ローカル変数LVarをつくる
MsgBox, , %A_ScriptName%, This is function`nGvar = %GVar%`nLVar = %LVar%
}
実はもう一手間必要で、関数内で改めてグローバル変数宣言を行うことで、参照ができるようになる。
GVar = hoge ; グローバル変数GVarをつくる
MsgBox, , %A_ScriptName%, This is plain command`nGvar = %GVar%`nLVar = %LVar%
; LVarは空
TestFunc()
; GVar/LVarとも出力される
Exit
TestFunc() {
global GVar ; GVarをこの関数内においてグローバル変数として宣言する
LVar = fuga ; ローカル変数LVarをつくる
MsgBox, , %A_ScriptName%, This is function`nGvar = %GVar%`nLVar = %LVar%
}
つまるところ、関数内においては、あらゆる変数がいったんローカル変数として参照されるわけだ。
スーパーグローバル変数
日本語資料がロクになくて苦労したのだが、上記の問題はスーパーグローバル変数として宣言することで解決できる。
Functions#Super-global variables
Super-global variables [v1.1.05+]: If a global declaration appears outside of any function, it takes effect for all functions by default. This avoids the need to redeclare the variable in each function.
やり方は簡単で、関数外において、変数をグローバル変数として宣言すればよい。
スーパーグローバル変数は、関数内での宣言がなくとも、あらゆる関数内で自動的にグローバル変数として参照される。
global GVar ; GVarをスーパーグローバル変数として宣言
GVar = hoge ; グローバル変数GVarをつくる
/* こういう書き方でもいい
global GVar := "hoge" ; グローバル変数GVarをつくる
*/
MsgBox, , %A_ScriptName%, This is plain command`nGvar = %GVar%`nLVar = %LVar%
; LVarは空
TestFunc()
; GVar/LVarとも出力される
Exit
TestFunc() {
LVar = fuga ; ローカル変数LVarをつくる
MsgBox, , %A_ScriptName%, This is function`nGvar = %GVar%`nLVar = %LVar%
}
逆に言えば、関数内の処理だけで、スーパーグローバル変数を宣言することはできない。
なにやらclassがどうこうとかも書いてあるのだが、さっぱり理解できないので諦めた。
引数渡し
また別の方法としては、グローバル変数を引数として渡してしまうというのもある。
GVar = hoge ; グローバル変数GVarをつくる
TestFunc(GVar) ; GVarを引数として受け取り、ローカル変数ArgVに格納
; ArgV/LVar共に出力される
Exit
TestFunc(ArgV) {
LVar = fuga ; ローカル変数LVarをつくる
MsgBox, , %A_ScriptName%, This is function`nGvar = %ArgV%`nLVar = %LVar%
}