Previous Page
Next Page

12.8. Reference as Parameter

You can pass a value that is a reference as a parameter to a handler, and it remains a reference. 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)

That code successfully changes the name of a folder in the Finder.

You can pass as a parameter a reference to anything you can usefully make a reference to. Thus, the reference to operator almost provides a solution to the problem of passing by reference (see Chapter 9):

on doubleRef(theRef)
    set contents of theRef to 2 * theRef
end doubleRef
script s
    property x : 5
    display dialog x
end script
doubleRef(a reference to s's x)
run s -- 10

But this solution is not completely general, and indeed no completely general solution is possible, because you can't usefully make a reference to a local. Also you'll notice that the example worked only because the handler doubleRef knew in advance that it was going to be handed a referenceit explicitly dereferenced the reference in order to change the thing referred to. So passing a reference is a way to allow a handler to change a value in place, but this is not the same thing as passing by reference, and it doesn't work if the value to be changed is a local variable.

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 "Microsoft Entourage" to set y to message 1 of in box folder
getNameOfAnything(x) -- "Mannie"
getNameOfAnything(y) -- "Order Confirmation"

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 what is returned from findInList is a direct pointer to the desired item of the original list, and so we can change that item, in place.


Previous Page
Next Page