What’s the worst that could happen if I stop using my libraries and just duplicate their handlers, and any handlers they are dependent on, into my scripts?
The problem I’m running up against is that I frequently hit AppleScript’s stack limit on larger scripts. I’ve broken my libraries up by function category or application that they address, but If I need one handler from each of the FileSystem, Array, String, Photoshop, and Math libraries, I have to load ALL of those libraries’ handlers. Some of my libraries are large, and I’m usually using only a fraction of their handlers in any given script. But all of their code is loaded into the script context. It seems like the obvious solution is to further segment my libraries so I can load less unused code. But I’m currently at 19 libraries. This led me to think that the extreme version of this solve would be single-handler libraries. Madness!
Instead, I’ve written a script that lets me choose one of my libraries, and then it presents that library’s handlers for me to choose from. It inserts a call to a chosen handler into the front Script Debugger document at the current cursor position, if the handler is new to the script then it jumps to the end of the script and inserts the handler’s source code. It checks the newly added handler for any dependencies and loads those handlers, recursively checking each one for dependencies, and then returns to the original cursor position. Done. This way, I have easy access to any of my handlers, but only the necessary code is loaded into the script context.
This has completely resolved my issues with the memory stack issue. Now I’m trying to imagine any possible pitfalls that I’m digging for my future self.
If a handler in one of my libraries gets updated, I’d have to replace that handler in every script that uses it to get it to use the new code. On the upside, existing scripts will be absolutely stable and won’t alter their behavior if a library changes. This is a wash as far as I’m concerned. Most of my scripts have limited lifespans, and those that are persistent will continue to work just as they are. If a script must be updated then I have a script that can easily replace the handlers’ code in it for me.
This is only for my own script libraries, third party libs would still be used normally. So, what could I run into later that I’ll wish I’d thought of? Worst-case scenarios are appreciated here.
I truly don’t understand how that would help. Maybe I don’t understand what the issue is.
Explain it to me like I was an AI bot.
(The purpose of handlers in Libraries is so you don’t need to duplicate code. If you change the handler in the library, you shouldn’t have to change it in every script that uses it, as long as the input and the output are the same.)
I may have made this sound like I have a question about libraries. The issues I have with libraries is completely of my own making. Well my choices and the relatively modest code limits that AppleScript has.
I have too many big libraries. If I try to use them in the way I want I get errOSAInternalTableOverflow errors. There are multiple solutions to this but none that I was happy with so I decided to stop using the libraries directly but to script the embedding of only the required handler code from any of my libraries into my scripts. This doesn’t load any unused code and I like the workflow.
If I were copy pasting handlers or using a code clippings app I would wonder the same thing. Is there anything I haven’t considered in writing and distributing and maintaining scripts over time without using libraries.
Edit: I’m sure I confused the whole thing in my opening question. That should have read “ What’s the worst that could happen if I stop using my libraries and just duplicate some of their handlers, and any handlers they are dependent on, into my scripts?”
I get what you’re trying to do, but honestly I think you’re just asking for trouble
Having 19 libraries tells me that you love writing AppleScript and you write a lot of it
That’s why I think you’re asking for trouble. I broke my libraries down by function type and it works well for me, so I’ve been thinking about your question and how it would apply to my own scripts.
Having to remember which scripts contain which version of which functions would just be too much for me. I’d say maybe a compromise might work: do what you suggested (put the handlers into the scripts) and write a script that puts the version number of each handler at the start of the scripts that use it. Then have a regular handler that checks if the version number has changed and alerts you to which scripts need updating (it could even paste the updated script in at the end of your code and comment it out, so it’s ready for you to incorporate)
It’s still extra work, and the other thing is that it is so error-prone. I’ve lost count of the number of times I’ve got caught out by a change I made to a handler that required an extra variable, but forgot to update one of the scripts calling that handler
Your suggestion could work, you could find a way (like the versioning I mentioned above) to make sure you always update the relevant scripts, and carry on coding
But as a guy who writes a lot of scripts for things other people would think are absurd, I gotta say it really seems like a whole lot of work, a whole lot of error-checking, and a whole lot of failed scripts when you forgot to initialise a variable somewhere
Having libraries that contain only one function each actually sounds like quite an elegant solution, as long as the libraries have names that are easy to recall when you want to use them. If reducing the amount of code that gets sucked into your scripts is the goal, I honestly don’t see anything wrong with having the smallest libraries you can get away with
The solution is to breakup your big libraries into more, smaller libraries.
As for having to rewrite scripts calling the libraries, try using records as a format what the libraries return (yes this would mean rewriting all the scripts that call the libraries one time, but just once).
As an example I have a dateformatting library that I’ve been using for years for numerous projects and its output has evolved over the years to account for different uses. The library handlers return their results as a record.
So when the script calls the library it gets, for example, the PageFolioDate of DateLibararyFolioDates
Suppose I’m generating folioDates for another publication, I would edit the library and add to the record it returns magazinePageFolioDate. The original scripts would still get their value in exactly the same way, but the new scripts could get the new value too. So there would be no need to change the old scripts that call the library.
I feel like you’re right with this general assessment.
Busted.
I honestly was just kidding, but I think you’re right here too. In a way.
Agreed. Using normal library loading techniques I think this is the only solution available to us. Fortunately, I think that I’ve found another way forward.
I’m not going to post my solution just yet. I’m still testing and confirming it, but I believe that I’ve found a way to load all of my libraries into my scripts easily, with no issues with compiling or saving scripts despite their having access to all 623 handlers. I even have a script that offers all these handlers to me and inserts the selected handler call in my current script. This script adds a propery definition for each used handler so that they are available at the top level without the need to address them by their library.
So, all my libraries handlers are available with a call to ‘library’s handlerName()’ or directly addressable by ‘handlerName()’ if I add a property to make them local. If my library loading method testing proves successful I’ll share my method and scripts.
I take this approach with handlers that return a number of results, but I aim to have the simplest handlers possible, ideally returning a single result. This usually does make for more handlers in general.
If this were any other mainstream language, with the possible exception of Forth (don’t ask), you would be OK. But AppleScript? Do you have any hair left?
I only have a couple of libraries (that don’t get used much), but have used individual insertion wrappers for some common handlers that I make available in the Script Menu.
I’ve thought about bundling a bunch of them into an XML or property list file to avoid a lot of the redundant insertion code or maybe using run script or load script so that the code would only be in memory when it is used, but then it would wind up like Automator or something. Might be interesting to compare notes, although I don’t have near as many handlers or projects to use them in.
lol. ok, TBH almost a third of them are PhotoShop handlers. But then again, to be fair, I’ve been being super conservative about adding to my libraries, and that may just change.
I’ve had a long and fun AppleScript journey. I think I started writing AppleScript in 1995, my earliest library that I still have in my archive is from 2012, and I still have a ‘parse carracho logs’ script from 2002. Flashback! Does anyone remember ScriptBase? My libraries are all the results of years of gradual code accumulation and acquisition.
About a year and a half ago I decided to standardize all my code and also modernize ( ASObjC ) everything that I could. I just slowly worked my way through it all. No deadlines. Creating a little pocket of order feels pretty good and helps me relax. I wrote some tools to make it easier too. I also didn’t write all this code! I referenced every applescript resource available. I’ve rewritten it all for my libraries, but also credited code consistently in the past year and retroactively everywhere that I could. This Macscripter board has been an invaluable source of code, knowledge, support and ideas!