Question

Why do these even exist? It seems absurd. Like with most dynamic languages, AppleScript types seem to be either immutable primitive types like integers and reals which are going to be handed around by value and don't make any sense to use with a reference to, or object-like types like applications, scripts, or records, which are being passed around by reference already. How is a reference to not completely redundant? Here's an example taken from Apple's AppleScript Language Guide (http://developer.apple.com/library/mac/#documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html if you've lost the link):

tell app "Finder" to set diskRef to a ref to startup disk
--result: startup disk of application "Finder"

So do you mean to tell me that if I did this instead,

tell app "Finder" to set diskObj to startup disk
--result: startup disk of application "Finder"

that the applescript runtime is going to send an apple event sent across to the Finder process telling it, "hey - some guy just asked you to return an octet stream of /dev/disks01 back to me! Haha! I guess he should have asked for a reference to it! Let's get started! This is going to take a while!"

I'm programming in Python and I do this:

m = fileHandle.read( 1000000000 ) #and then wait a little while
n = m 

Did I just copy a gig of data around in memory? Of course not. But the existence of a reference to in AppleScript implies that assigning objects to new variables is a by-value operation. And if that's the case, what's the deal with the copy command?

What's going on here?

UPDATE: Well, just consider me a confused Python programmer. Just to make this a bit more clear, I still think

tell app "Finder" to set diskRef to a ref to startup disk
--result: startup disk of application "Finder"

is a poor example (taken from the applescript language guide). But @Chuck's example of a reference to the property itself holding a primitive type that can then be reassigned is a better one. IOW, a reference object is really a variable/property that holds a pointer to another variable or property.

Was it helpful?

Solution

My understanding is that you can think of references as pointers.

set x = 5
set y to reference to x
set contents of y to 10
log x -- 10

In general, you don't manually create references. AppleScript libraries and dictionaries may return them, but then you work with the properties of the returned item (name of startup disk for example).

Honestly, I'd ignore them. In twenty years of working with AppleScript, I've probably had to look up the documentation to references once. If you're trying to do something in AppleScript and believe you need to create a reference variable, you're probably not doing it in the most straightforward manner.

Check out this MacTech article for a more detailed discussion of AppleScript references.

OTHER TIPS

Two variables in AppleScript, like in Python, can share the same value. Each variable has a reference to its value, but the word "reference" has other meanings. The string "https://stackoverflow.com/" is a reference to a web site; the integer 42 is a reference to the works of Douglas Adams; and an object of class reference in AppleScript is a different kind of reference.

An object of class reference postpones access to an element or property of some object. It's almost like a lambda in Python, because the AppleScript

set v to {11, 22, 33}
set r to a reference to item 2 of v

acts like the Python

v = [11, 22, 33]
r = lambda: v[1]

by postponing access to the 2nd item of a list. Then contents of r in AppleScript or r() in Python would get the item. AppleScript can also set the item with set contents of r to 99; Python can't set the item with this lambda. Python's lambdas can do many things that AppleScript's references can't do.

a reference to operator

The AppleScript Language Guide describes the a reference to operator but misses some important details. The operator has one operand; the compiler also accepts reference OPERAND or ref OPERAND, then rewrites them as a reference to OPERAND.

If the operand is an expression of the form A of B or B's A, then the operator wraps the expression in an object of class reference. This expression can be an element, like item 2 of q, or a property, like length of q.

If the operand is a variable, then the operator attaches an implicit my or of me. For example, a reference to q in the run handler is the same as a reference to my q. This becomes confusing in scopes where q and my q are different.

For other operands, then the operator only returns the operand. For example, a reference to 3 returns 3, which is not an object of class of reference.

The operator captures the current value of variables. For example, a reference to item i of q captures the values of i and q. For contrast, a reference to q doesn't capture the value of q, because it is the same as a reference to my q, so it sees q as a property, not a variable.

to demo()
    set q to {11, 22, 33}
    set rq to a reference to q
    set i to 2
    set ri to a reference to item i of q
    set i to 3
    set item 2 of q to 55
    set q to {77, 88, 99}
    {contents of rq, contents of ri}
end demo

set q to "a string"
demo()

The result of this script is {"a string", 55}. Reference rq ignored the local q and used my q from the run handler. Reference ri captured the local values of i and q, ignored later assignments to i and q, but didn't ignore the assignment to item 2 of q.

Using references with big lists

The AppleScript Language Guide also has examples using the a reference to operator to increase the speed of accesses to a big list. The Guide uses

set bigListRef to a reference to bigList

but fails to explain that the reference is implicitly a reference to my bigList, so the access is through the script object me. It only works because the code is in the run handler, where bigList and my bigList are the same list.

It turns out that accesses to a big list are fast if the reference goes through any script object. Other accesses are slow. The next script shows this by creating a list of 7000 items using fast accesses, and then reading the list using both slow and fast accesses.

to bench(what)
    set start to current date
    repeat with i from 1 to 7000
        if item i of what is not 42 then
            error "wrong value"
        end if
    end repeat
    (current date) - start
end bench

to bench2()
    script box
        property nums : {}
    end script
    repeat 7000 times
        set end of box's nums to 42
    end repeat
    {bench(box's nums), bench(a reference to box's nums)}
end bench2

bench2()

I ran this script on my old machine running PowerPC Mac OS X 10.4.11. The result was {19, 0}, so the slow accesses took 19 seconds, and the fast accesses took 0 seconds.

The line set end of box's nums to 42 does a fast access without using the a reference to operator. It is fast because the access goes through box, a script object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top