Variables in SenseTalk
Variables are named containers. They serve as holders for values, similar to the “memory” function on a calculator. Unlike most simple calculators, which have only a single memory location that holds one number, you can store many values at once in different variables. Also, the value stored in a variable is not limited to a single number, but can be an arbitrarily large amount of data. To keep track of the different variables, each one has a name.
Names of local, global, and universal variables must begin with a letter or an underscore character (_). The name can be any length and can contain letters, digits, and underscores. All variable names are case-insensitive (upper-and lower-case letters are treated as equivalent).
Local variables are the most common. They exist within the context of a single handler in a script. To create a local variable, you simply put something into it in a script. For example, the command put 5 into foo will create the local variable foo if it doesn’t already exist and store the number 5 in it.
Local variables cannot be accessed outside of the handler (or script) where they are used. References to foo in another handler will be to a separate foo that is local to that other handler. Local variables are temporary: their values go away when a handler finishes executing. Suite variables also are considered local in scope; see Creating and Using Suite Variables for more explanation of these variables.
Parameters declared after the handler name in an on or function declaration are a special type of local variable. Parameter variables are different from other local variables because when the handler begins executing they already contain values passed by the sender of the message. Other local variables have no initial value when the handler begins executing.
Local variables that have not yet been assigned a value will ordinarily be treated as unquoted literals—in other words, their value is the same as their name:
put Hello -- Displays "Hello"
Sometimes this behavior can lead to trouble, such as if you inadvertently misspell the name of a variable later in the script and expect it to have the value previously stored in it. To help with debugging your script in such cases, or if you simply prefer a more rigorous approach, you can set the strictVariables global property to true. When this property is set, any attempt to access a variable that has not been explicitly declared or assigned a value will throw an exception rather than returning the variable’s name:
put Bonjour into greeting -- Stores "Bonjour" in the variable greeting
set the strictVariables to true
put Bonjour into greeting2 -- Throws an exception
Global variables can be referenced from any handler within a project. Unlike local variables, global variables retain their value between different handlers. While local variables are undefined at the beginning of a handler each time that handler is called, global variables might already have a value that was assigned previously, either by the same handler (on an earlier call to it) or by a different handler.
To create and use global variables, they must be declared as global within each handler where they are used, so that SenseTalk can distinguish them from local variables. This is done using the global keyword. The global keyword can be used at the beginning of a line, like a command, followed by a list of the names of variables being declared as globals. This type of declaration must appear before any other use of those variables in the handler. Usually, therefore, it is good practice to place global declaration lines at the beginning of a handler, as in this example:
global didItBefore -- Declare the global variable
if didItBefore is true then -- Don't allow it to be done twice
answer "Can’t do it again!"
put true into didItBefore
It is also possible to refer to a global variable without declaring it in advance, by simply preceding its name with the global keyword in any expression. Using this approach, our example could be rewritten like this:
if global didItBefore is true then
-- Don't allow it to be done twice
answer "Can’t do it again!"
put true into global didItBefore
Because global variables are "global", they can be accessed from any handler in any script within a project. This provides a useful means of sharing information between different handlers. Care must be taken, however, not to use the same global variable name for different purposes in different parts of a project.
For example, if you used the doSomethingUniquely handler above to keep an action from being performed twice, and then copied and pasted the same handler into a different script (changing only the dotheThingToBeDone line) so that some other action would also be restricted to running just once, you would have a problem. Both scripts would now be using the same global variable (didItBefore) to keep track of whether their action had already been performed, so the first one that calls its doSomethingUniquely handler will prevent the other one from performing its action at all!
To solve this problem, you would need to use different global variables in each handler, by changing the variable names (didSomethingBefore, didTheOtherThingBefore, etc.) or come up with some other means of distinguishing between the two cases.
The globalNames() function (or the globalNames) can be used to get a list of the names of all global variables that have been assigned values.
Universal variables must be declared using the universal keyword, either on a separate declaration line sometime before they are referenced in each handler where they are used, or immediately before the variable name within any expression, in a manner identical to that for global variables.
The universalNames() function (or the universalNames) can be used to get a list of the names of all universal variables that have been assigned values. The following example will display the names and values of all universal variables:
repeat with each item of the universalNames
put "Universal " & it & " is " & value("universal " & it)
Variable Types Summary
In summary, there are three distinct types of variables that you can use in your scripts.
- Global and universal variables must be declared in each handler that uses them, or else preceded by the word global or universal each time they are used.
- Undeclared variables that are not preceded by the word global or universal within a handler are local to that handler.
- Local variables have a value within a single execution of a single handler, and are discarded when the handler finishes executing.
- Global variables have a value that persists across handlers. They are discarded at the end of a run.
- Universal variables are similar to global variables, but typically have a larger scope as defined by the host application. For example, in Eggplant Functional, universal variables have a value that persists across handlers and across runs. They are discarded when Eggplant Functional quits.
The three types of variables are all distinct (that is, you can have local, global, and universal variables all in existence at the same time with the same name but different values).
Variables are created automatically by assigning a value to them. They can also be deleted, using the delete variable command, or one of its variants.
delete variable holder -- Makes local variable "holder" undefined again
delete local password
delete global accountNumber
delete universal pendingTasks
Metadata in Variables
In some cases, variables might contain extra information (also known as metadata) in addition to the ordinary value (the data) that they contain. For example, when a variable holds a date or time value, the actual data (the value) that is stored in the variable is a number that specifies an instant in time. In addition to this time value, the variable also holds a format that specifies how the value should be presented to the user or represented when the value is requested as text (see Date and Time Values in SenseTalk).
As another example, when a variable holds a list, the list of values that it contains is the data (contents) of the container. The metadata in this case is the currentIndex value that allows the list to be used as an iterator (see Ranges, Iterators, and Each Expressions).
In each of these cases, in addition to the data contents of the variable, SenseTalk makes the metadata accessible to the script as a property of the variable:
put the date into currentDate
put currentDate -- 10/22/10
put currentDate's format -- %m/%d/%y
put "%Y" into the last two characters of currentDate's format
put currentDate -- 10/22/2010