References to Containers
Most of the time, containers in a script are used by storing a value directly into a container—or reading a value from one—by simply specifying a variable name (or other container identifier) directly in the script. Sometimes it can be extremely useful, however, to store a reference to a container, which can later be used to access the value of that container. The reference holds the identity of a container rather than its value, and accessing the reference will read or write the contents of the container that it refers to.
Characteristics of References
References have a few characteristics that you will want to be aware of as you work with them. To begin to understand how references work, consider the following example using a reference to a simple variable:
put 32 into age -- Age is now a variable containing the value 32
put a reference to age into yearsOnThePlanet -- Store a reference
put yearsOnThePlanet -- 32 (yearsOnThePlanet refers to age's value)
add 1 to age -- Age is now 33
put yearsOnThePlanet -- Puts 33 (references are dynamic)
In the first line above, a simple value (32
) is assigned to an ordinary variable (age
). The next line stores a reference to the variable age
into the variable yearsOnThePlanet
. Now, any access to the value of the yearsOnThePlanet
variable will actually be accessing the value of the age
variable, as illustrated by the next line of the script, The last two lines of the script increment that value of the age
variable and show that the yearsOnThePlanet
variable accesses the updated value.
References Bind Tightly
The connection established by a reference is “sticky” (yearsOnThePlanet
is glued tightly to age
in the above example) so assignments work in the other direction as well — changing the value of either will change the value of both:
put 29 into yearsOnThePlanet
put age -- Puts 29
Reference Syntax
References can be made using the words container
, reference
, reference to
, or refer to
, or using the shorthand symbol @
before the container. Or using by reference
or as reference
after the container. All of the following are equivalent:
put container thing into watcher
set watcher to be a reference to thing
put @thing into watcher
set watcher to reference thing
set watcher to refer to thing
set watcher to thing by reference
set watcher to thing as a reference
Syntax:
container aContainer
{a} reference {to} aContainer
refer to aContainer
@ aContainer
aContainer [by | as {a}] reference
References Can Be Stored in a List or a Property List
References can not only be stored in variables, as shown in the examples so far, but may also be stored as items in a list, or as properties of an object or property list. In this case, accessing the specific item or property that is a reference will access the container it refers to, as shown in this example:
put 13 into luckyNumber
put ["horseshoe", container luckyNumber, "penny"] into charms
put charms -- [horseshoe, 13, penny]
put 7 into item 2 of charms
put charms -- [horseshoe, 7, penny]
put luckyNumber -- 7
References May Refer to Properties, Files, and Chunks
References may refer to any type of container, not just variables. This includes all the different types of container discussed earlier in this section, including properties, files, and even chunks of any container:
set highScore to reference item 2 of line 3 of file "/tmp/stats"
put @ item 2 delimited by "." of the numberFormat into decimalFormat
References Are Dynamic
When a reference is made to a property of an object or to a chunk of a container (such as reference to word 3 of sentence
) that reference is evaluated dynamically each time it is used. This means that if the contents of sentence
are changed, the reference will always access the third word of its new contents.
References Are Not "Contagious"
Assignments in SenseTalk are always done by value unless a reference is explicitly indicated. So assigning a variable containing a reference to another variable will not create another reference, but only a copy of the current value of the source container. To create another reference, you must specifically indicate a reference during the asignment (specifying a reference to a reference will result in a second reference to the same source).
put 123 into source
put a reference to source into ref -- 123 (ref is a reference)
put ref into number -- 123 (number is NOT a reference)
put @ref into ref2 -- 123 (ref2 is now another reference to source)
put 456 into source
put ref -- 456
put number -- 123
put ref2 -- 456
References Can Be Reassigned
Storing a reference into a variable that already contains a reference will simply reassign that variable to the new reference. It will not change the value that the variable previously referred to:
put [123, 456] into [source1, source2]
put a reference to source1 into ref
put ref -- 123
put a reference to source2 into ref -- Ref is now reassigned
put 789 into ref -- Source1 is unaffected
put [source1, source2] -- [123, 789]
To change the container that was referred to into a reference instead of reassigning the original reference variable, you can request that explicitly using container referred to
:
put @source1 into the container referred to by ref -- Ref still refers to source2, which now becomes a reference to source1
put "We're Twins" into ref -- Assign to ultimate container
put [source1, source2] -- [We're Twins,We're Twins]
Deleting By Reference
Deleting a reference to a chunk or property with the delete
command will delete the chunk or property it refers to (note that this is not the same as deleting the variable containing the reference — see below).
put [1,3,5,7,9,11,13] into odds
set num to refer to item 5 of odds
put num -- 9 (num refers to item 5)
delete num
put odds -- [1,3,5,7,11,13]
put num -- 11 (num now refers to the new item 5)