• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Tell Blocks Considered Harmful (was Re: open for access)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
  • Follow-Ups:
    • Re: Tell Blocks Considered Harmful (was Re: open for access)
      • From: Chris Page <email@hidden>
References: 
 >Re: Tell Blocks Considered Harmful (was Re: open for access) (From: Bill Cheeseman <email@hidden>)
 >Re: Tell Blocks Considered Harmful (was Re: open for access) (From: Chris Page <email@hidden>)

  • Prev by Date: Opening Smart Mailbox in Mail
  • Next by Date: Re: Tell Blocks Considered Harmful (was Re: open for access)
  • Previous by thread: Re: Tell Blocks Considered Harmful (was Re: open for access)
  • Next by thread: Re: Tell Blocks Considered Harmful (was Re: open for access)
  • Index(es):
    • Date
    • Thread