DekGenius.com
[ Team LiB ] Previous Section Next Section

7.6 Lifetime of Variables

The lifetime of a variable means just what you think it means—how long the variable lives.

A local variable is born when it first is assigned a value, and dies when the scope in which it was born stops executing. A variable that behaves this way is sometimes called an automatic variable, because it comes into existence and goes out of existence automatically. For example:

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

Well, you already knew what would happen when that code runs. But what I'm saying now is something you can't see, and I can't quite prove, so you'll just have to believe me: by the time we get to the last line of that example, the local x inside myHandler isn't just unavailable, it's gone. It came into existence as myHandler was executing, and it went out of existence when myHandler finished executing.

A top-level entity other than a local variable is persistent. This means that its name and its value survives the execution of the script. This becomes interesting and relevant if you execute the same script twice.

Here's a simple example. Create this script in a script editor program and run it:

property x : 5
set x to x + 1
display dialog x -- 6

Now run it again, without doing anything else. Here's what happens:

property x : 5
set x to x + 1
display dialog x -- 7

This amazing result is possible because AppleScript has a memory. (You did reread Section 4.2.4, didn't you?) Your compiled script is in AppleScript's memory. After the script is executed, AppleScript retains the compiled script, and along with it, all the top-level entities that resulted from its execution. This includes properties, so after the first execution of the script, AppleScript is remembering that the script has a property x and that its value is 6. Thus when you run the script a second time and x is incremented, it becomes 7.

Now, at this point, you are saying: "But wait! I can see x being initialized to 5 right in the first line of the script. So what about that line? Are you saying that, the second time the script is executed, AppleScript is ignoring that line?" Well, it's really just a matter of what initialize means. It means to give a value to something that has no value. The second time the script is executed, x has a value already, remembered from the previous execution. So the property declaration has all the usual downward effects of a property declaration; but the initialization part of it has no effect, because x doesn't need initializing.

You can do the very same thing with a top-level global variable, but it's a little trickier because you need a way to initialize the global—to give it a value if it doesn't have one, but not if it does. Obviously this won't do:

set x to 5
set x to x + 1
display dialog x -- 6

You can execute that over and over, and it just displays 6 over and over. The problem is that set is not a mere initialization; it sets x regardless. Thus you keep resetting x to 5 each time you execute the script. This means that you probably don't believe me when I say that the value of x is being remembered between executions. To get around this, we have to use stealth (and some syntax that hasn't been discussed yet—try blocks are explained in Chapter 12):

try
        set x to x + 1
on error
        set x to 5
        set x to x + 1
end try
display dialog x -- 6, then 7, and so forth

Run that repeatedly. Now do you believe me?

A script object defined at top level is a top-level entity, so it and all script objects defined within it, and therefore all their properties, also persist after execution. For example:

script outerScript
        script innerScript
                property x : 5
                on increment(  )
                        set x to x + 1
                end increment
        end script
        tell innerScript to increment(  )
        display dialog innerScript's x
end script
run outerScript -- 6, then 7, and so forth

Now, nothing lives forever, so just how long does all this persistence persist? Well, for one thing, it all comes to an end if you edit the script. That's because altering the script means that the script must be recompiled, and at that point the contents of the old compiled script, including the values of the top-level entities from the previous execution, are thrown away from AppleScript's memory. That's why throughout this section I've been telling you to execute the script multiple times without doing anything else.

The really, really surprising part, though, is that this persistence can survive the saving and reloading of the script in a script file. Unfortunately you can't see this if you save or open the script file using the current Script Editor. It doesn't work with Smile, either. Smile has another way of implementing persistence between sessions. So try it with the old version of the Script Editor (1.9), or with Script Debugger. Create and run this script several times:

property x : 5
set x to x + 1
display dialog x

Now save the script as a compiled script file, and quit, just to prove to yourself that AppleScript's own memory of the value of x is well and truly erased. Now open the compiled script file again and execute it. The incrementing of x picks up right where it left off previously.

This mechanism is not automatic. AppleScript itself has no way to enforce file-level persistence, because AppleScript itself doesn't deal in files. It is up the environment that's talking to the AppleScript scripting component, after it asks AppleScript to run the compiled script file, to save AppleScript's copy of the compiled script back into the compiled script file after execution. If it doesn't do this, then the compiled script file won't contain the new values, and the values won't persist. Fortunately most environments, including applets, as well as script runners such as the Script Menu or BBEdit's Scripts menu, are well-behaved in this regard. But as we've just seen, the current version of Script Editor is not. This inconsistency can be troublesome.

    [ Team LiB ] Previous Section Next Section