Re: AS Library Question
Re: AS Library Question
- Subject: Re: AS Library Question
- From: has <email@hidden>
- Date: Wed, 16 Dec 2015 15:54:17 +0000
Shane Stanley wrote:
> On 16 Dec 2015, at 10:31 AM, Stan Cleveland <email@hidden> wrote:
>>
>> The libraries I use are custom-made for the work here.
>
> [...]
>
> The solution is to basically to be aware of it, and probably avoid
properties within libraries where they're not really needed. And you can
do things like add some kind of initialization handler that scripts
should run first before they call others.
Not a great idea, as now you've got several scripts contesting over who
set what last. Bear in mind that OSA isn't just about running scripts in
simple batch-processing; it can also load and persist scripts and
repeatedly call their handlers over time.
If library code needs to be stateful, use OOP, e.g.:
-- Foo.scpt library:
on makeFoo()
script Foo
property someState : ...
on someCommand()
...
end someCommand
end script
end makeFoo
-- your script:
set myFoo to makeFoo() of script "Foo" -- create a new Foo object to
reuse throughout your own code
someCommand() of myFoo
Another possibility is to do:
copy myLib to script "SharedLib"
which does a deep copy of the original loaded library, giving your
script its own personal copy with its own private state. However, that
probably won't work recursively (i.e. if the library you copied itself
uses other libraries, those will probably remain shared).
A third option, and often the clearest and safest, is to create a
record/script object in your top-level script that contains all the
state your libraries need access to, and pass that object as an
additional parameter to your library-based handlers when you call them.
Bit tedious (since you may be passing the record through lots of
handlers that don't need it just to make it available to the few that
do) but at least it makes all these dependencies absolutely explicit.
I suppose if you were really desperate for a 'reliable' library loader
(or just don't fancy rewriting your existing AM Loader-based systems to
use AS's loader), you could even turn AM Loader into an AS library
itself. The Loader object itself works well enough (if you don't mind
writing lots of grotty `importLib()` boilerplate), and uses `load
script` so avoids any hidden sharing with unrelated scripts. As I said
in my previous post, the big technical weakness of AM Loader is that it
relies on an osax to bootstrap it. The osax hides all the hassle of
locating and loading the actual Loader object into your script behind a
simple standard `property _Loader : AppleMods Loader` statement that
goes at the top of your script. Third-party osaxen can be problematic to
say the least these days, especially unmaintained ones, but the same
stuff could be done just as easily by an AS library now.
> There are also cases where a persistent lib property makes sense.
Something like a number formatter in an ASObjC-based lib, or simply
where you scripts to share some info.
For the first, you'd probably use OOP to create and return your custom
number formatter, which you then retain in your own code while using it.
The one thing you might safely keep in such a library is a cache of,
say, previously created instances, if creating those instances is a
particularly expensive process (e.g. regex libraries often cache
recently-parsed regular expressions so that if the user makes lots of
find/replace calls with the same pattern string it can avoid the
overhead of re-parsing that pattern every single time).
For the second, yeah, putting state such as preferences that are shared
across your system in a library is easiest (caveat the usual concerns of
safety, understandability, and maintainability from having lots of
shared state across a system).
> And if you don't run scripts from within other apps, you can just
ignores it.
Unsafe advice: even if your current usage avoids the problem, you should
be including cautionary comments at the top of such libraries warning
future maintainers that the library contains mutable state and thus will
cause obscure and hard-to-identify malfunctions should two completely
unrelated scripts try to load and use it at the same time. Otherwise if
you later forget, or the code passes to someone else to maintain, or you
choose to distribute those libraries to other users, it's just a booby
trap *waiting to happen* should your or their usage patterns differ or
change in future.
(And this is why I get so narked about sloppy thoughtless design by
"responsible experts" building stuff intended for large numbers of
regular users to work with. Users would *never* need to know nor care
about such insanely technical problems had developers not created them
in the first place. Hell, *no-one* should have to dredge through
impenetrable warnings like these. But this is why I switched to other
more reliable languages for all my serious automation work years ago:
while they still have plenty issues of their own, at least their leaks
don't spring anywhere as often or easily as AS's do.)
Regards,
has
--
p.s. Stan, the Apple mailing list archives definitely don't like you as
I don't see your new post there either. Feel free to cc/email me
directly if you've any specific questions you need answered.
_______________________________________________
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