DekGenius.com
[ Team LiB ] Previous Section Next Section

11.6 Reference as Parameter

You can pass a reference as a parameter to a handler, and it remains a reference. The fact that the variable where the reference is stored may be a local is irrelevant; so is the fact that the parameter is local to the handler.

So, for example:

local x
tell application "Finder"
        set x to folder 1
end tell
on setName(theRef)
        set name of theRef to "Jack"
end setName
setName(x)

In that code, x is a local, and theRef is too (because a handler parameter is local within the handler). But the code still works; it changes the name of a folder in the Finder.

But you can't pass a reference to a local, because you can't make a reference to a local. Well, you can, but you can't use it as a reference. That's why the reference to operator can't provide a general solution to the problem of passing by reference (see Chapter 8).

So, for example:

global x
local y
set x to 5
set y to 5
on doubleRef(theRef)
        set contents of theRef to 2 * theRef
end doubleRef
doubleRef(a reference to x)
display dialog x -- 10
doubleRef(a reference to y) -- error

The difference between x and y in this code is purely that x is global while y is local. Applying the contents of operator to x works; applying it to y causes an error.

The use of a reference as a parameter can permit a handler to perform dynamic targeting. As long as a handler doesn't use any vocabulary that depends on a specific target, it can target an application whose identity is not known until runtime. In this example, the same code in the same handler is able to target the Finder and Mailsmith indiscriminately:

on getNameOfAnything(theRef)
        return name of theRef
end getNameOfAnything
tell application "Finder" to set x to folder 1
tell application "Mailsmith" to set y to mailbox 1
getNameOfAnything(x) -- "Mannie"
getNameOfAnything(y) -- "(drafts)"

A handler or script object can also return a reference. Of course, this cannot be a reference to a local variable. It must be a reference to something that the handler or script object can obtain a reference to. For example, it can be a reference to a property:

script myScript
        property x : 3
        return a reference to x
end script
set y to run myScript
set contents of y to 10
myScript's x -- 10

Or it can be a reference obtained from a scriptable application:

on getFolderByNumber(n)
        local x
        tell application "Finder"
                set x to folder n
        end tell
        return x
end getFolderByNumber
getFolderByNumber(1) -- folder "Moe" of desktop of application "Finder"

And it can be a reference to a parameter that is a reference or was passed by reference. You can get some rather powerful effects that way:

on findInList(what, L)
        repeat with i from 1 to count L
                if item i of L is what then
                        return (a reference to item i of L)
                end if
        end repeat
        return
end findInList
local pep
set pep to {"Mannie", "Moe", "Jack"}
set contents of findInList("Moe", pep) to "Larry"
pep -- {"Mannie", "Larry", "Jack"}

That's quite similar to return-by-reference in C++. The handler findInList returns a reference to a particular item of L; in this case, it returns the reference item 2 of {"Mannie", "Moe", "Jack"}. Thus we are now pointing at the desired item of the original list and can change that item, in place.

    [ Team LiB ] Previous Section Next Section