An explicit local is a variable whose name appears in a local declaration . A local declaration can declare several variables at once, delimited by comma:
local a local b, c, d
A local variable is visible only within the very same region of scope where it is declared—not outside it, and not at a deeper level. (But there's an exception, which we'll come to in a moment.)
Local variables completely disambiguate a name within their own scope, and local variables in other scopes can have the same name without conflict. Suppose a script object starts like this:
script myScript local x
The local declaration for x
means that from now on when code in this script object's scope says x
it means this local x
and no other. What's more, other scopes may declare their own local x
, they may declare a global x
, they may bang the floor and have a temper tantrum, but they absolutely will not be able to have any effect upon myScript
's x
, nor will anything myScript
does with its x
have any effect upon them.
Here's an example of a local variable in action:
local x
set x to 5
script myScript
display dialog x -- error: The variable x is not defined
end script
run myScript
Observe how completely different this is from what would have happened if x
had been a top-level property. Here, there is a variable called x
and it is defined, but it is declared local and therefore is visible only within its own scope. That scope is the top-level script. The display dialog x
command is in a different scope, that of the script object myScript
. Therefore AppleScript takes this to be a different x
, and this different x
has never been assigned a value. (I'll explain later just what x
AppleScript takes the x
of display dialog x
to be.)
A local declaration overshadows the visibility of a top-level entity from a higher level:
property x : 5
script myScript
local x
display dialog x -- error: The variable x is not defined
end script
run myScript
But this overshadowing affects only the scope of the local declaration—not a deeper scope:
property x : 5 script myScript local x on myHandler( ) set x to 10 end myHandler myHandler( ) set x to 20 end script run myScript display dialog x -- 10(not 20)
The dialog displays 10
, not 20
. Even though myScript
overshadows the top-level property x
with a local x
declaration, this has no effect on myHandler
, which still sees the top-level property x
. (This makes sense, because it can't see myScript
's local x
.) When myHandler
sets x
to 10, that is the same x
as at the top level. When myScript
sets x
to 20, that's its local x
, and the value displayed in the last line is unaffected.
In a handler, the variable names used for parameters in the definition of the handler are local within the handler. Naturally, a handler may also declare further locals:
on myHandler(what) local x set x to 7 end myHandler myHandler("howdy") display dialog what -- error: The variable what is not defined display dialog x --error: The variable x is not defined
Now we come to the great exception: a script object defined in a handler can see the handler's local variables. To a script object in a handler, the handler's locals are like top-level entities: they are visible to the script object and to scopes nested within it. (We took advantage of this rule in "Power Handler Tricks" in Chapter 9.) Thus:
on myHandler( )
local x
set x to 5
script myScript
on h( )
display dialog x
end h
h( )
end script
run myScript
end myHandler
myHandler( ) -- 5
I think the reason for this rule is that a handler can contain a nested scope (a script object) but has no top-level entities. A handler can't declare a property, so without this rule, it would have no encapsulated way to expose values to a nested script object. Similarly, without this rule, code in a script object in a handler would be unable to see a script object earlier in the same handler:
on h( )
script s
display dialog "howdy"
end script
script ss
run s
end script
run ss
end h
h( ) -- howdy