AppleScript_ The Definitive Guide - Matt Neuburg [97]
At top level, it is not an error to declare a variable global and then declare it local in the same scope. But the global variable is effectively overshadowed by the local in the top-level scope. For example:
global x
set x to 5
local x
on getX( )
display dialog x
end getX
getX( ) -- 5
display dialog x --error: The variable x is not defined
After the first two lines, there is a global variable x and its value is 5, and code at a deeper level can access it; the subsequent local declaration has no effect on this fact, even though it precedes the definition of the deeper-level code. But the top-level code has apparently lost its access to this global variable. It can recover this access, however, through the use of the keyword my:
global x
set x to 5
local x
set x to 10
x -- 10
my x --5
The same thing happens if a global is implicitly redeclared as local by a repeat block (see "Repeat With" in Chapter 19):
global x
set x to 10
repeat with x from 1 to 5
end repeat
x -- 5
my x --10
It is not a compile-time error to redeclare a top-level entity as a local or a local as a top-level entity, but access to the top-level entity is lost within that scope:
script myScript
property x : 4
display dialog x
local x
display dialog x
end script
run myScript -- 4, then error: The variable x is not defined
The second attempt to display x fails because by that point x has been redeclared as local, and this local has no value. But the downward effect of the property declaration remains, so the property remains accessible at a deeper scope. Thus:
script myScript
property x : 10
local x
set x to 20
on myHandler( )
display dialog x
end myHandler
myHandler( )
display dialog x
end script
run myScript -- 10, then20
It is a compile-time error to redeclare as global a variable declared as a top-level entity in the same scope:
property x: 10
global x -- compile-time error: Can't declare x as both a local and global variable
It is not a compile-time error to do it the other way around, redeclaring a global as a top-level entity. This is merely taken as a delayed declaration of the top-level entity, and the global declaration has no effect. So:
global x
set x to 10
script myScript
global x
set x to 5
property x : 20
display dialog x
end script
run myScript -- 5
display dialog x --10
Within myScript, x is a property throughout; the global declaration inside myScript has no effect. The property x starts out with the value 20 before myScript runs, but myScript then sets it to 5, and this is the value that is displayed in the first dialog. The second dialog shows that the global x is unaffected. This code was written and executed on a closed course by a trained driver; please, do not attempt.
Closures
A closure is one of those delightfully LISPy things that turns up in AppleScript. The subject is rather advanced, though, so don't feel you have to understand everything in this section at once.
It turns out that a script object may capture certain aspects of its context, maintaining this context even though the script object may run later in a different context. For example:
property x : 5
script myScript
display dialog x
end script
set x to 20
set dummy to myScript
set x to 10
run myScript -- 20
That is extremely odd. It violates the rule stated earlier ("Free Variables") about the value of free variables being determined at runtime. By the time myScript runs, its free variable x has been set to 10, yet the dialog displays 20. The proximate cause turns out to be the mysterious line "set dummy to myScript." If that line is removed, the dialog says 10, just as we expect. Yet it is hard to see what difference that one line can make. It's not as if we ever do anything with the variable dummy, after all. We simply assign to it and forget about it. So what's going on?
The rule appears to be