AppleScript_ The Definitive Guide - Matt Neuburg [94]
Code not at the top level
The variable is created as a local. I call this an implicit local .
Let's illustrate an implicit global first:
set x to 5
on getX( )
global x
display dialog x
end getX
getX( ) -- 5
The first line never said explicitly that x should be a global. But it clearly is one, since when getX comes along and asks to see a global called x, the x created in the first line is what it sees. (Incidentally, you can move the "set x to 5" line to after the getX handler definition and the script will still work; the important thing is that the global x be defined by the time getX runs, not necessarily before getX itself is defined.)
Incidentally, a variable created implicitly in a script's top-level explicit run handler is an implicit global as well, just as if you'd declared it at the absolute top level:
on run
set howdy to "Howdy"
sayHowdy( ) -- Howdy
end run
on sayHowdy( )
global howdy
display dialog howdy
end sayHowdy
That's a very odd rule, as in no other respect (I believe) is an explicit run handler treated like the absolute top level; usually, it's treated like a handler, in which case the implicit variable would be local. This shows the extremes the language goes to in order to cope with undeclared variables.
Now for an implicit local:
set x to 5
on getX( )
set x to 10
display dialog x
end getX
getX( ) -- 10
display dialog x --5
Clearly we are now talking about two different variables called x. We have already established that the top-level x is global; but getX is evidently not seeing it. It is setting to 10, and displaying, some other x; its actions are having no effect on the top-level x, as the last line proves. So getX's x must be local to getX. To prove that it is truly local and not some sort of magic downward global within getX, we need another test:
script s
set x to 10
on myHandler( )
display dialog x
end myHandler
myHandler( )
end script
run s -- error: The variable x is not defined
But if we reverse the structure—a script object in a handler, instead of a handler in a script object—then it works:
on getX( )
set x to 10
script s
display dialog x
end script
run s
end getX
getX( ) -- 10
That isn't because x is not local; it's because of the special exceptional rule that a script object in a handler can see the handler's locals.
Declare Your Variables
Sounds like "eat your vegetables," doesn't it? Well, it should. Each motto is good advice, no matter how unpalatable it may seem at first. I strongly advise you to declare all your variables—even (especially!) your locals. Unfortunately, AppleScript gives you no help with this; you can't make it warn you when a variable is undeclared. Rather, it silently declares it for you. This behavior, doubtless intended to make programming in AppleScript easier, is in fact the source of more mistakes and confusion among AppleScript programmers than any other feature of the language.
The trouble is that if you are lulled into a false sense of security because there's no need to declare your variables, then you can be surprised when some other scope tramples them. For example, imagine that your script starts like this:
set x to 5
That's top-level code, so you've just implicitly declared x a global. This means that any other handler or script object anywhere in this script can access your x and change its value, just by saying this:
global x
This other code may not have intended to trample on your x; perhaps it was trying to establish a global of its own, possibly in order to communicate its value to code at a lower level, or to function as persistent storage between calls. But the damage is done, just because of the upward effects of a global declaration. And to think that you could have prevented this by declaring your top-level x local to start with.
The converse is also true. Pretend that you have a large script and that this code occurs