Re: Tell Blocks Considered Harmful (was Re: open for access)
Re: Tell Blocks Considered Harmful (was Re: open for access)
- Subject: Re: Tell Blocks Considered Harmful (was Re: open for access)
- From: Ed Stockly <email@hidden>
- Date: Wed, 10 Dec 2008 12:34:24 -0800
The other Chris, no, not that one, the first Chris, once explained to
me how the AppleScript language implemented the Object Hierarchy found
in HyperCard with OSAX.
It made perfect sense, I've been implementing it for years, and while
it's far from perfect it makes for very editable, readable and useable
scripts.
In Hypercard, you have buttons and fields contained in cards that are
part of backgrounds that are in stacks that are linked to a home stack
that is inside Hypercard.
If a button gets a command from its script that it doesn't recognize,
that command is passed up the hierarchy to the card, if the card
doesn't recognize it, it goes up to the hierarchy to the background,
the stack, the home stack and to the application until either it is
recognized or generates an error.
Tells in applescript behave in a similar way.
The main thing is to keep tell blocks small and to not put
extraneous commands inside them, especially scripting addition
commands, which are a maintenance issue because they can collide
with future changes to application terminology.
But that's how the technology has been designed and used for all these
years and aside from a few terminology conflicts that crop up every
now and then, it's pretty well worked.
As for terms colliding with future changes to application terminology,
Apple should be providing application and scripting addition
developers some kind of database that they can use to ensure that
their new terminology doesn't conflict with current terms and someone
to maintain that database (an AppleEvent Registry, if you will!)
But even without a Registrar for most of AppleScript's life, there
have been remarkably few terminology conflicts.
It can also be a problem for someone examining or editing a script
(even the original author) to tell whether a command is being sent
to another process on purpose. It’s more difficult for them to tell
how the script was intended to behave if tell blocks aren’t used
judiciously.
Does it really matter? Is it really that important to know if it's the
Finder that processes the choose file command or an Osax? And there
are some cases, like choose file, where the scripter may want the the
execution in the finder in order to display the dialog in the Finder's
user interface.
As a scripter learns more about appleScript they learn those details
as they become more important. (It would help if there is still an
AppleScript user list that welcomes beginners and doesn't become a
shell scripters users list that frightens them away or only offers
shell scripting solutions to simple appleScript questions).
But you are saying that this snippet is NOT OK, at least in
principle:
tell application "TextEdit"
tell application "Finder"
tell window 1
-- multiple statements affecting Finder window 1
end tell
end tell
end tell
Right?
Yes, that’s one example of undesirable tell block use. In that
particular case, nested “tell application” blocks make it confusing
which application is providing which terminology and handling which
commands. One really should never nest “tell application”, because
at best the inner “tell application” overrides the outer one,
rendering it pointless. Nested tell blocks should be reserved for
referring to objects within a given application.
Since the nested tell overrides the outer tell there is no problem or
conflict. And it's fairly evident what application is responsible for
what action to the writer and the reader.
This design has a purpose. To make scripts easier to read, easier to
write and simpler to follow, which in turn, made scripting accessible
to non-programmers (Your truly). Those concepts were considered more
important in the design of the language than absolute clarity about
what process is handling what command. That's a good thing.
The general case is wrapping most or all of a script within a “tell
application” block when most of the script doesn’t use that
application’s terminology or explicitly mention any of that
application’s objects with specifiers. I think what happens is
people think “I’m scripting Finder” and so they just start with
‘tell app “Finder”’ and write their entire script without paying
much attention to which parts of their script actually involve Finder.
I recently ran into a script with several dozen lines of code
wrapped in ‘tell app “System Events”’ in which only the very first
line--a “path to” command--needed a tell at all.
Did the script compile? Did it run? Was it one of mine? In my scripts
I often include "path to" commands in application tells, even though
it's an osax command and the application is not needed.
It might not be a bad idea for the AppleScript compiler to perform
some optimization of tell blocks (assuming such a thing is
possible). When you compile a script it could be changed to reduce
the size of tell blocks to only surround blocks of code that
actually need them, and isolated lines of code could be changed to
use tell statements.
First, that sounds like a huge undertaking to fix something that's not
really broken. I'm sure there are higher priority items for Apple
Engineers to work on. Second, you're suggesting having the compiler
completely alter the structure of working scripts, in a way that may
be incomprehensible to a new user (or even and experienced scripter).
Another thing that might be useful is to issue a compile-time
warning (or perhaps even an error) if there are nested “tell
application”s.
Which would basically make it harder to learn to script. That working
script you cited above would suddenly not work or the scripter would
see scary error messages for no real reason. That could add hours to
the process of learning-to-write-scripts-as-you're-writing-your-first-
scripts.
Another reason to avoid throwing lots of commands into tell blocks
is because the implementors of scripting additions (e.g., me) can’t
tell whether you’re intentionally sending the commands to another
process or if it’s an accident of how the script was written. For
many commands this can be an important concern because the
semantics--the meaning--of performing a command in one process
versus another may be significantly different.
For example, “open for access” opens a file and creates a Unix file
descriptor in the process running the command. The interpretation of
file paths, permissions and the limit on the number of open files
all depend on the process performing the command. Whether or not the
command succeeds or the script works as intended depends on which
process it sends the command to. If a script unintentionally sends
“open for access” to other processes, it may work today, but in the
future it may not.
I can see how that creates a potential problem, but I don't believe
it's an actual problem. Most of those commands will go to either the
Finder, an FBA or whichever application the scripter is scripting.
I've never had an Open for access command fail for that reason, and I
can't remember seeing a message on this list attributable to this
scenario.
Perhaps worse, when there are lots of scripts unnecessarily sending
commands to other processes, the implementor of a scripting addition
can’t know whether it’s safe to alter the command in ways that might
not be compatible. For example, let’s say I wanted to change “open
for access” to operate with the permissions and current working
directory of the sending process instead. I can’t really know
whether someone out there is sending this command to another process
to intentionally use that other process’s state. Someone might, for
example, tell another process to open a file so that the file
remains open across multiple runs of the script--a very, very bad
idea, but someone may rely upon it.
Well, in that case I'd say don't change open for access. It works,
it's not broke, don't fix it.
If script authors keep tell blocks to a minimum, that makes it
easier to tell what’s intentional and what’s not, for people using
or editing scripts and for implementors of scripting commands.
Yes it may make it more of a challenge for implementors of scripting
commands, but one of the things I like best about AppleScript (and
Apple itself, for that matter) is it makes things harder for
developers, but if they do the work it's easier for the users.
It's one thing to encourage scripters to keep tell blocks to a
minimum, it's quite another to propose radical changes in the
compiler, breaking working scripts for very little benefit.
Seriously, if it's not broke don't fix it. Don't make the good the
enemy of the perfect.
HTH,
ES
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden