AppleScript_ The Definitive Guide - Matt Neuburg [77]
This is true for a handler too, if we simply treat the handler as the value of a variable:
script s
on h( )
return 10
end h
end script
tell s
get h
end tell
Again, we get an error that h is undefined.
But a handler call is different. This works without its:
script s
on h( )
return 10
end h
end script
tell s
h( ) -- 10
end tell
So a handler call is automatically treated as an attempt to access a top-level entity. It's important to stay conscious of this, because if you go by your intuitions alone you may be confused. Consider this script:
script x
property greeting : "Howdy"
on myHandler( )
display dialog greeting
end myHandler
script y
display dialog greeting
myHandler( )
end script
end script
run x's y -- Howdy, then error: «script y» doesn't understand the myHandler message
It looks like the property greeting and the handler myHandler are in the same place, so they should have the same status. And that's true, as far as it goes. But y apparently can see greeting, yet it fails in its attempt to call myHandler. That is also true. The reason is that a handler call is not the same thing as just saying the name of some variable. A handler call is routed as a search for a top-level entity. The search starts in y. myHandler isn't there, so we pass to the parent. The parent isn't x; it's the top-level script. myHandler isn't there either. So the search fails. This is not to say that you can never call myHandler at all. You simply have to target x explicitly when you do:
script x
property greeting : "Howdy"
on myHandler( )
display dialog greeting
end myHandler
script y
x's myHandler( ) -- explicit target
end script
end script
run x's y -- Howdy
I think the reason for this special status of a handler call is that AppleScript wants to treat a handler call as a command. Its status is like that of the built-in commands, such as run and count. When you give a command to a script object, you don't want to have to talk in some special way; you are sending a message and you want that message to go to the right place all by itself. So a handler call works that way too.
To see that this probably the right sort of explanation, consider how the message-passing mechanism works when you send a built-in command to a script object:
script s
end script
tell s to count -- 0
The count message is routed just the way a handler call is routed. If a script object implements count, it is this count that is called:
script theCount
on count
return "1, 2, 3, ha ha ha"
end count
end script
tell theCount to count -- "1, 2, 3, ha ha ha"
Alternatively, if we give s a parent that implements count in a different way, then the count command is routed to that parent:
script s
property parent : {"Mannie", "Moe", "Jack"}
end script
tell s to count -- 3
(We'll return to weird handlers like count in Chapter 9, and to objects and the message-sending mechanism in Chapter 11.)
So it appears that the inheritance chain is involved in every command. Whether it's a handler call or a built-in command, it has some target and is passed up the inheritance chain from that target until we come to someone who can obey. This probably also explains the curious language of the error message you get when you misdirect a handler call to a scriptable application:
tell application "Finder"
sayHowdy( ) -- Finder got an error: Can't continue sayHowdy.
end tell
It's as if the Finder were a sort of script object, saying, "I don't know what this command means, and I haven't got a parent to pass it along to."
Because handler calls and commands are passed up the inheritance chain, the current application is the implicit target of every command not otherwise targeted. This fact is rarely useful, though. For example, in theory, if a script that drives BBEdit is to run in BBEdit's Script menu, it doesn't need to target BBEdit in a tell block; BBEdit is the current application, so