Previous Page
Next Page

10.5. Scope of Globals

An explicit global is a variable whose name appears in a global declaration . A global declaration can declare several variables at once, delimited by comma:

global a
global b, c, d

Globals are rather complicated. I'll divide the discussion into two parts: the downward effect of a global declaration, and its upward effect.

10.5.1. Global Declarations: The Downward Effect

The downward effect of a global declaration is very much like a top-level entity declaration. A variable declared global is visible in the scope where it is defined, subsequent to the point where it is defined, and at all deeper levels within that scope, subsequent to the point where it is defined.

For example:

global x
set x to 5
on myHandler( )
    display dialog x
end myHandler
myHandler( ) -- 5

The variable x is declared global; it is then visible downward into the scope of myHandler, because myHandler is defined subsequently in the same scope as x.

But the following code does not work:

set x to 5
on myHandler( )
    display dialog x
end myHandler
global x
set x to 10
myHandler( ) -- error: The variable x is not defined

We keep setting x like mad, but to no avail; the global declaration doesn't come until after the handler definition, so code inside the handler can't see x.

Just as with a top-level entity, a global's downward effect is overshadowed by a local declaration of the same variable name at a deeper level, and this overshadowing affects only the scope of the local declarationnot a deeper scope.

10.5.2. Global Declarations: The Upward Effect

The upward effect of a global declaration of a variable is to identify that variable with a variable at the top level of the script with the same name (creating this variable if it does not already exist). This means that separate regions of scope can share a variable simply by declaring it global:

on setX( )
    global x
    set x to 5
end setX
on getX( )
    global x
    display dialog x
end getX
setX( )
getX( ) -- 5

That example demonstrates that the two handlers are sharing the same variable x. Now let's demonstrate that this x is being instantiated at the top level:

on setX( )
    global x
    set x to 5
end setX
setX( )
display dialog x -- 5

The fact that the last line works, rather than generating a runtime error complaining that x is not defined, shows the call to setX has defined x at the top level.

The status of a global created in this way is interesting. First, observe that it is not automatically visible downwards, as it would be if a global declaration (or a property declaration) were present at the top level. This doesn't work:

on setX( )
    global x
    set x to 5
end setX
on getX( )
    display dialog x
end getX
setX( )
getX( ) -- error: The variable x is not defined

Even though x is a global defined at the top level, as we proved in the previous example, yet now getX can't see it. There is no global x declaration at a higher level than getX, so there is no downward effect to endow getX with the ability to see x. And getX itself now contains no global x declaration, so in effect it has failed to put in a request of its own to see x.

10.5.2.1. Global as static

A local is not persistent it goes out of scope and is destroyed each time its scope finishes executingbut a global is. So a global is one way to implement a static variable (that is, a variable that will persist between executions of the local scope):

on incrementOrReport(report)
    global ct
    if report then return ct
    try
        set ct to ct + 1
    on error
        set ct to 1
    end try
end incrementOrReport
incrementOrReport(false)
incrementOrReport(false)
incrementOrReport(false)
incrementOrReport(true) -- 3

However, that is really poor programming style; a script object and a property would let you do this in a far more encapsulated way.

10.5.2.2. Global as script property

A global is, in fact, persistent between script executions, just like a script property. This is a little tricky to prove, because we need a way to initialize the global only just in case it isn't already defined; to do this, I'll have to use some syntax we haven't discussed yet (see "Errors" in Chapter 19):

on setX( )
    global x
    try
        set x to x + 1
    on error
        set x to 5
    end try
end setX
on getX( )
    global x
    display dialog x
end getX
setX( )
getX( ) -- 5, then 6, and so on

Indeed, a global isn't merely like a script property; it is a script property. Again, I have to be a little tricky to prove it to you:

on setX( )
    global x
    set x to x + 1
end setX
on getX( )
    global x
    display dialog x
end getX
setX( )
getX( ) -- 6, then 7, and so on
property x : 5

In that example, I deliberately postponed the property declaration until after all the other code, to show that it isn't the property declaration itself that is making x visible in lower scopes (remember, a top-level entity is visible to nested scopes only after its declaration). Thus it must be the global declarations within setX and getX that are identifying x with the script property x at the top level.

Here's another way to show that a global is a script property: I'll use a global to give the anonymous top-level script a name , and then I'll speak of another global as a property of the top-level script. This is a rewrite of a device from "The Implicit Parent Chain" in Chapter 8, using globals instead of properties at the top level:

global topLevel, x
set topLevel to me
set x to 5
script s
    property x : 10
    display dialog topLevel's x
end script
run s -- 5

Observe that a global declaration lets a scope region refer to an entity defined at the top level of the script, even when its name is overshadowed by a top-level entity at a deeper level:

global x
set x to 10
script outer
    property x : 20
    script inner
        global x
        display dialog x
    end script
end script
run outer's inner -- 10

Without the global x declaration in inner, inner's x would be outer's property x, and the script would display 20. This script works the same way if the top-level x is declared as a property, not a global; they are the same thing. Thus we have another solution to the problem of how to speak of the top-level entities of a script as a whole even though it is anonymous (see "The Implicit Parent Chain" in Chapter 8).

10.5.2.3. The double effect of global declarations

In working with explicit globals, remember that every global declaration has both the downward and upward effect at the same time:

script myScript
    global x
    on myHandler( )
        set x to 5
    end myHandler
    myHandler( )
end script
on getX( )
    global x
    display dialog x
end
run myScript
getX( ) -- 5

In myScript, the global x declaration does two things: it creates the top-level global x (upward effect), and it gives myHandler access to it (downward effect). Thus myHandler is able to set the value of the top-level global that will later be seen and displayed by getX.


Previous Page
Next Page