15.8. Who Performs an OperationSome 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 OperationsAccording 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 SpecifiersIn 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. |