15.8. Who
Performs
an Operation
Some operations within an interapplication communications context can be performed by the target application rather than by AppleScript. There are two cases to consider. The operation may appear as a bare expression (for example, the condition in an
if
clause); I will call this a
direct
operation . Or, the operation may be part of a boolean test element
specifier
.
15.8.1. Direct Operations
According to Apple's documentation, if the first operand of a direct operation is a reference to an object of the target application, the target application should perform the operation. So, for example:
tell application "Finder"
if name of folder 1 contains "e" then
The object
name of folder 1
is a Finder object, so in this case, according to Apple, the Finder should perform the operation. However, experimentation shows that the Finder does
not
perform the operation; AppleScript does try to get it to do so, but the target application replies with an error indicating that it doesn't wish to perform that
sort
of operation. AppleScript thereupon adopts a new strategy: it asks the target application for the values in question, and performs the operation itself.
So, here's how that example really works. AppleScript starts by sending the Finder a single Apple event that means: "Please tell me whether the name of your folder 1 contains
"e"
." The Finder replies with an error message. So then AppleScript
tries
the other strategy: it goes back to the Finder and sends it another Apple event that means: "Okay, never mind that, just tell me the name of your folder 1." The Finder complies, and now AppleScript looks, itself, to see whether the result contains
"e"
.
This approach seems wasteful, but it is
wasteful
only the first time. The second time the same sort of code is
encountered
, the AppleScript scripting component remembers that the Finder doesn't do this sort of operation, and skips the first step; it just asks the Finder for the value of the operand and does the operation itself.
In fact, I have not found
any
application that appears willing to perform direct operations when AppleScript asks it to! The entire matter is therefore moot. One can see, all the same, that the mechanism is a good idea. For example, there is no way to ask an application whether two references are references to the very same thing:
tell application "Finder"
set f1 to folder 1
set f2 to folder "Mannie"
f1 = f2 --
false
end tell
These are in fact one and the same folder, and it would be really great if the Finder could tell us so. In order for this to happen, though, the Finder would have to perform the comparison, and it simply isn't going to. Similarly, in this code:
tell application "Finder"
if name of folder 1 is name of folder 2 then
It would be efficient to be able to ask the Finder, with a single Apple event, to perform this comparison and report on the result. As it is, AppleScript ends up sending the Finder two Apple events (one asking for the name of folder 1, the second asking for the name of folder 2) and performing the comparison itself.
15.8.2. Boolean Test Element Specifiers
In a boolean test element specifier (see Chapter 11), the target application
always
performs the comparison itself. For example:
tell application "Finder"
name of every folder whose name contains "E"
end tell
That is a single Apple event; the Apple event includes instructions to use
contains "E"
as the criterion for returning folder
names
, so the Finder must implement
contains
in order to obey.
Differences between an application's implementation of an operator and AppleScript's implementation can arise under these circumstances. This seems rather scary, but if the application is well-behaved, these differences should be minor. The primary case in point is the use of
considering
clauses. For example:
tell application "Finder"
considering case
name of every folder whose name contains "E"
end considering
end tell
--
{"emptyFolder", "Test Me"}
The Finder gives the wrong answer; if you consider case,
neither
of these folder names contains
"E"
. The Finder is simply ignoring the
considering
clause. In fact, I don't know of
any
application that considers
considering
clauses in a string comparison. (See "String Considerations" in Chapter 19.)
The workaround in a situation like this is a two-step approach: fetch all the values and then have AppleScript perform the test itself. AppleScript does not implement boolean test element specifiers for lists, so the test must be performed as a loop:
tell application "Finder"
set L to name of every folder
end tell
set L2 to {}
considering case
repeat with aName in L
if aName contains "E" then
set end of L2 to contents of aName
end if
end repeat
end considering
After that,
L2
contains the right answer. Fortunately, such an approach is not particularly expensive in this case; luckily, the Finder implements
get name of every
(see "Operations on Multiple References" in Chapter 11), and the test we perform in the loop doesn't involve sending any Apple events.
|