10.9. Redeclaration of VariablesRedeclaration of variables is a nasty edge case, testing the limits of the language. Luckily, the compiler mostly stops you from doing it. But there is a great deal of legal nuttiness, especially among declarations at the top level of a script. Essentially AppleScript is hoist with its own petard: having ruled that variables can be declared implicitly, and that global variables exist at top level even when they are declared elsewhere, AppleScript is simply trying to cope coherently with the consequences. Here are some examples of what happens when you redeclare a variable. It is a compile-time error to redeclare an implicit global as local: set x to 5 local x -- compile-time error: Can't declare x as both a local and global variable It is a compile-time error to redeclare an implicit local as global: on getX( ) display dialog x global x -- compile-time error: Can't declare x as both a local and global variable end getX By the same token, it is a compile-time error to declare a handler parameter as global within the handler: on myHandler(what) global what -- compile-time error: Can't declare x as both a local and global variable end It is a compile-time error to redeclare as local a variable declared global in the same scope (except at the top level): on getX( ) global x local x -- compile-time error: Can't declare x as both a local and global variable end getX It is a compile-time error to redeclare as global a variable declared local in the same scope (except at the top level): on getX( ) local x global x -- compile-time error: Can't declare x as both a local and global variable end getX At the top level, it is not an error to declare a variable local and then declare it global in the same scope. But it doesn't have any effect within the top-level scope either. For example: local x global x set x to 5 on setX( ) set x to 10 end setX on getX( ) display dialog x end getX setX( ) getX( ) -- 10 display dialog x -- 5 Once x is declared global, both setX and getX have automatic access to a global variable x. But the code in the top level does not have such access. There, x has already been declared local; nothing can change this. Once a local, always a local. The x that is set to 5, and that is displayed at the end, is this local x, which is different from the global x. 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, then 20 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. |