Re: AS Library Question
Re: AS Library Question
- Subject: Re: AS Library Question
- From: has <email@hidden>
- Date: Sun, 06 Dec 2015 17:12:03 +0000
Shane Stanley wrote:
>On 3 Dec 2015, at 9:01 AM, Stan Cleveland <email@hidden> wrote:
>>
>> Any thoughts?
>
> I can't point you to any documentation,
Undocumented behavior is undocumented. If it isn't in the user
documentation then don't do it, because it wasn't intended to be done;
rather it's an oversight or flaw in the language design.
While handlers may be implemented as objects of type `handler`, that's
purely an internal implementation detail. Unlike, say, JavaScript or
Swift functions, which are actually closures (i.e. they remember the
scope in which they were defined) that can be created and passed around
safely as first-class objects, AppleScript handlers are not designed to
operate or be manipulated as independent objects, but only as part the
script object within which they were defined. Moving a handler from one
script object to another breaks its static variable bindings, which
leads to delightfully nasty and unexpected bugs:
script Foo
property greeting : "hello"
on welcome()
say greeting
end welcome
end script
Foo's welcome() -- says "hello"
script Bar
property spanners : {}
property yob : missing value
end script
set Bar's yob to Foo's welcome -- This is evil and wrong; do not do.
Bar's yob() -- this breaks because doStuff has lost its binding to
`greeting` property and wrongly tries to use the `spanners` property instead
If you want to pass a handler around, the correct way to do it is to
wrap it in a script object and pass that around instead. For example, if
you want to parameterize a `sortList` handler with a custom handler that
knows how to compare all sorts of different values (strings, numbers,
lists, records, etc):
script CompareCaseSensitiveText
on isLessThan(value1, value2)
considering case
return value1 as text < value2
end considering
end isLessThan
end script
script CompareCaseInsensitiveText
on isLessThan(value1, value2)
ignoring case
return value1 as text < value2
end ignoring
end isLessThan
end script
on sortList(theList, comparisonObject)
...
if comparisonObject's isLessThan(leftItem, rightItem) then ...
...
end sortList
set theResult to sortList(myList, CompareCaseSensitiveText)
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, but since Apple scrapped the original AS team
shortly after its 1.1 release few of them ever got fixed (and compared
to its more egregious flaws this one is pretty small beans).
To reiterate: don't do that; it's a recipe to make things break. Use the
language as it's designed and documented to be used.
> 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. (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.
> Hang on, Matt Neuburg's book has something to say on it:
>
> "A handler is a datatype in AppleScript. This means that a variable's
value can be a handler. In fact, a handler definition *is* in effect the
declaration (and definition) of such a variable."
But see above. Honestly, if this sort of technical guff is of interest
to you, the best thing to do is to go learn some other languages
(especially better designed ones, although most are pretty crap to be
honest) as that will give you a far broader perspective on what kinds of
language features are possible, how they work and why (i.e. what
problems do they solve), and why a given language chooses to include the
features it does. If you can find a nice tutorial on writing your own
simple Scheme-like 'toy' interpreter (which these days you easily can do
in any old scripting language[1]; no need to suffer C masochism), then
it'll give you a lot of insight into how little mystery or magic is
really involved.
has
[1] e.g. The kiwi language I wrote for driving Illustrator artwork
automation <http://www.mantasystems.co.uk/documentation> is implemented
in Python as a dumb AST walker which is as slow and primitive as they
come, but it's still more than fast enough to beat a human operator on
the same task. And while it's gotten a bit more complex than a toy
Scheme interpreter, that's really all it started out as.
_______________________________________________
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