On Dec 6, 2015, at 9:12 AM, has <email@hidden> wrote:
While handlers may be implemented as objects of type `handler`, that's purely an internal implementation detail.
That is incorrect (or, at least, overstating the case): while it may not be well-documented, the existence of handlers as objects is part of the public interface of AppleScript, and of the OSA API. They can explicitly be displayed as “«handler foo»” and “handler” is a public class—you can ask for the class of a handler and get back “handler”, you can programmatically test whether an object is a handler, and you can invoke it by sending it a message. As in AppleScript, fetching the value of a property via OSA can return a handler, the result of executing a script can be a handler, and OSA's OSAExecuteEvent can be used to execute a handler.
e.g., in AppleScript we can send a message to a handler like so:
on foo(x) x end foo
set bar to foo tell bar to foo(42) --> 42
Note that a handler knows its name (which is why it can be displayed) and it only responds to a message with the appropriate name:
tell bar to bar(42) --> error "«handler foo» doesn’t understand the “bar” message." number -1708
However, the behaviors you describe obviously show that you can't arbitrarily assign them to some other script's property without relying on details that aren't explicitly documented. While I agree that one shouldn't try to rely upon some of those details, AppleScript and OSA are explicitly designed to support handlers as objects that you can introspect and send messages to, and they are not “purely an internal implementation detail”.
For example, you can use OSA to compile a handler without a surrounding script (without a “context”), then invoke it. You can even send it to another application process and execute it there. Although this isn't spelled out, these are designed to work. If something here doesn't work, file a bug.
The real problem is that AppleScript's `script` objects lack a mechanism for making slots read-only, as that would allow slots containing handlers to be locked down so they cannot be moved or replaced. But AppleScript is full of these sorts of design defects and oversights, as most first attempts are…
That is incorrect: it is not a flaw, it is a simple matter of…simplicity. AppleScript is a lightweight dynamic, object-oriented language like Self and Smalltalk—neither of which has read-only properties. AppleScript is hardly alone in this. Many dynamic languages don't have read-only properties.
More importantly: although it could be convenient to be able to declare a read-only property to make your intent clearer and to see errors if you inadvertently try to write one, not being able to declare a property read-only doesn't prevent you from being able to write scripts that do what you want. There is no missing capability here, only a minor convenience for catching errors in your code.
> Similarly, if you use load script: > > set x to load script "/Users/shane/Desktop/Test.scpt" > x's stripWhiteSpace > > And script libraries are really load script in new clothing.
That's technically incorrect: whereas `load script` creates new `script` objects within your current script (i.e. they become part of your own script's state), AS's official library mechanism loads scripts into the current Scripting Component Instance (CI) as new Script instances (OSAIDs) that live in parallel to your own scripts, and calls are passed from your scripts to library scripts using OSA's existing delegation system or [more likely] chicken voodoo.
Now who's relying on implementation details? ;-) Your apparently two different descriptions are in fact nearly identical, and there is no essential difference between scripts loaded with “load script” and scripts loaded via “script” element references, or, in fact, scripts defined in your source code. OSAIDs are an external reference for clients of OSA, but AppleScript doesn't use them internally (internally it just has pointers to objects, and OSAIDs map to pointers).
Apart from support for a search path, obviously, the primary difference between “load script” and ‘script "Foo"’ is that “load script” reads from the file every time and produces a new copy of the script, whereas script library references only load a given script once and produce the same one each time it resolves a reference to a library.
When you reference a library with ‘script "Foo"’ AppleScript resolves this reference and locates a script object, loading it from its file if it hasn't been already. At that point, it behaves just like any other script object. If you reference one of its properties or send it a message, it has exactly the same implementation as a script loaded with “load script” or, in fact, one defined in your script source. Typically the only other observable difference is that libraries always have an associated file to work with “path to” and so they can fetch their bundle resources, and other script objects may not, but this is merely a matter of having a (internal, implementation) property with the file location vs. not—there's no magic or difference in how they're implemented.
In fact, instead of using an element reference, you can even work directly with a script object loaded from a library, just as if it were loaded with “load script”. e.g. ‘set theScript to script "My Library"’. If you display the value of “theScript” you'll see a script object “«script My Library»” rather than a ‘script "My Library"” specifier. If you assign it to a property and save the script, the entire library script will also be saved, just as if you had written “set myProperty to load script …”. I strongly advise against that, of course, since it defeats the purpose of having libraries—you may as well copy and paste the library code into your script at that point.
The point is: no magic, nothing scary or weird. After it locates and loads a library script, it's the same as any other script object.
(Basically, official libraries = more design flaws, more complexity, and more opportunities to blow up on you when you're not expecting it.) Though since, as I say, you can't move handlers between script objects without breaking them - period - it doesn't really make a difference here.
Uh…what? Did you run out of caffeine? (I hate it when that happens.)
-- Chris Page The other, other AppleScript Chris
|