The use of global variables

I had a question as to the current thinking on the use of global variables. Just to demonstrate, I might have a script which is organized as follows:

main()
set aVariable to "a value"
-- other stuff
handlerOne(aVariable)
handlerTwo(aVariable)
-- 3 or more additional handlers all of which need aVariable
end main

on handlerOne(aVariable)
end handlerOne
on handlerTwo(aVariable)
end handlerTwo
-- 3 or more additional handlers all of which need aVariable

main()

The alternative to the above might be:

global aVariable

main()
set aVariable to "a value"
-- other stuff
handlerOne()
handlerTwo()
-- 3 or more additional handlers all of which need aVariable
end main

on handlerOne()
end handlerOne
on handlerTwo()
end handlerTwo
-- 3 or more additional handers all of which need aVariable

main()

Apparently, the second alternative may cause aVariable to be saved with the script every time it’s run, which seems undesirable. My questions:

  • How do other forum members handle this matter.

  • Is there some way to stop the script from saving aVariable if set as global with the script every time it’s run?

Thanks!

I happened upon a post which contained the following:

https://forum.latenightsw.com/t/sd8-where-did-it-go/2855

I assume that this does not apply to forum members using Script Editor.

Hi peavine.

The thinking on globals has always been to avoid using them if at all possible — to avoid both the problem you mention and possible scope collisions. It’s possible to restrict the scope of globals by declaring them only in the individual handlers which share them, rather than … er … globally at the top of the script. But they’re just like properties and run-handler variables when it comes to being saved back to the file. I don’t know if locking the file would work to stop this or simply generate its own error. Shane would be able to tell you more about what happens on systems more recent that my Mojave one. You’re right about Script Debugger scripts sometimes having non-standard behaviour. It may wow Script Debugger users, but it can make it difficult to define what the standard behaviour actually is. “The only way you can avoid this AppleScript feature is to switch to using Script Debugger.” :confused:

It’s a messy situation.

A script is essentially a script object. When you run it, if any top-level value changes, the script object itself has changed. And as designed, when a host (an applet, an editor, of something like FastScripts) ran a script, it called a function that checks if any values have changed, and if so, it would save the modified script. This was the basis of property persistence.

The exception was locked script files. They generate an error if you you try to save to them, and script hosts ignore that error.

When code-signing of applets came along, it was handled by changing the permissions of the script file to execute-only. Again, this generated an error, which is ignored.

Then along came ASObjC. ASObjC variables can’t be saved – they’re essentially memory addresses, so it would be pointless/dangerous – so saving such scripts also generated an error. Hosts were subsequently modified to ignore that particular error.

As security was tightened, GUI scripting authorization required that scripts sot change, so a new system was introduced whereby when you gave permission for a script, quarantine information was added to the file, which prevented normal saving.

In the middle of this, the problem for editors like Script Debugger was what to do: we wanted to create an environment as near to the reality of deployment as possible, but there was no way of knowing what that was. So Script Debugger 7 introduced the concept of a Persistent Properties setting, letting the user specify.

While that solved the problem for those who knew all the intricacies, it also confused many not aware of what was happening.

When Big Sur came out, with applet code-signing always on, we felt that the most common deployment target was now one where properties did not change, and that if anything, future changes would probably make it more so (there’s a more general security aspect, among other things). So we decided the best approach was to emulate that in Script Debugger 8, and simply remove the Persistent Properties setting.

Thanks Nigel and Shane for all the great information.

I edited the script that prompted me to start this thread and marked the affected variables as global only in those handlers where the variables were set or needed. I guess this is only half a solution but it did work well and it’s good to be aware of that option.

I ended up rewriting the script to largely eliminate this issue. My scripts tend to use handlers which call handlers which occasionally call handlers, and, without global variables, the number of positional parameters can become quite long. I guess a bit of advance planning is always the best solution.

I’ve switched to Script Debugger full time now, and it’s good to know that the use of top-level variables, globals, and properties won’t cause the script to save those values every time it’s run. This doesn’t help casual users of AppleScripts but they probably aren’t bothered by this issue as long as the script works.

I decided to run a few tests using the following script:

set testFolder to choose folder
tell application "Finder" to set fileList to (files of entire contents of testFolder) as alias list

I saved this script as an applet first in Script Editor, then Script Debugger, and finally Script Debugger with the Lock-main-script preference option enabled. I then ran the scripts on a folder that contained about 500 files and 100 folders and the script file-size results were as follows (all sizes are MB):

EDITOR - SIZE BEFORE FIRST RUN - SIZE AFTER FIRST RUN

Script Editor - 85 - 278

Script Debugger Script Locked - 92 - 285

Script Debugger Script Not Locked - 92 - 285

I was surprised that the script file saved with Script Debugger increased in size. I’m running Script Debugger version 8.0.1 (licensed).

peavine, can you email me the applet?

Shane. I sent you an email with two applets. Google refused to send the email, apparently because it contained an executable, so I sent it by way of another server (cableone). Hopefully you’ll get that.

Got it, thanks – I’ve amended the post accordingly.

I can’t check the locking because that tends to get lost in email unless you send as .zip file.

Thanks Shane. It’s good to understand how this works.