Why? An AppleScript record is a collection of properties whose structure is [normally] defined at compile-time, and they’re not designed or intended for the sort of manipulation you describe.
Unfortunately, it is occasionally necessary to do so when dealing with applications/osaxen that produce records with arbitrary structures at runtime (e.g. LNS’s XMLTools osax), in which case you can either use LNS’s List & Record Tools osax or various nasty vanilla hacks (both of which have various usability and reliability issues).
In the vast majority of cases though, what folk are actually needing is an associative list (aka dictionary, hash, map). Unlike most modern scripting languages, AppleScript doesn’t provide a built-in associative list type, but there are various third-party solutions you can use instead for storing arbitrary key-value mappings - e.g. Database Events, Satimage’s XMLLib osax, or Dictionary objects from AppleMods’ Types library.
The “Why?” is easy. I have a record whose structure (keys and values) is indeed defined at compile time. However, I have the need to create different lists from that record based upon variable information that comes from records in a database. The database records know the keys of each piece of data they need, so I need to programmatically pull the right data out of the record using the keys from each database record. But the keys themselves are static. It’s just which key that needs to be variable.
If it’s really not possible to access a key using a variable (which seems odd because it doesn’t muck around with the structure of the record at all), then I’ll have to look into the third party solutions you recommend. Any insight into which would support variables being used as keys? Would the solution still allow a chunk of data to be passed from one subroutine to another as records can?
Actually, it is possible. And, the hacks to do it aren’t exactly “nasty”… they’re just hacks. I will agree with hhas that applescript isn’t really meant to do this (thus the lack of support), so using any workarounds is at your own risk. When using applescript to handle records, it truly is best to find ways to create the record list using KNOWN keys and then find ways to access only these keys.
That being said, there are at least a couple posts hidden here at macscripter which have a method posted that uses the ‘run script’ command to do this. I also have a couple different implementations of the same concept posted on this page at my old geocities site. For simple implementations this will get you started. If you’re trying to organize anything but small lists of text, you’re probably going to risk overextending applescript’s capabilities… and should consider writing your app in another language.
That’s really an interesting approach. As I understand it, you are compiling a new script at runtime which allows you to use a variable string as a key. I’ll have to play with it. But as I need to do this many many times, I’m suspect that I’m going to either crash the system or slow it down to a crawl with this technique.
Is this record generated by your own code, or one created by a scriptable application? If the former, use a more appropriate data structure. If the latter, use LNS’s List & Record Tools osax, unless the record contains application references (which can’t be passed to osaxen) in which case you’ll have to use a vanilla hack.
Python and Ruby both have excellent application scripting support (see my sig for links) in addition to built-in dictionary/hash types that do exactly what you want. Well worth learning one or other of these languages, particularly if your programming needs are starting to outgrow AppleScript’s own limited capabilities.
Wow, that’s a life changing post! I poked around briefly at your sig links and I realized that it really is possible to use Ruby and Python. Not sure that I’m up to it on this project, but for the next…
I wasn’t sure that I understood the data structure page to which you linked. Is that a piece of software that you add to Applescript? The Associative List data object seems most appropriate for my needs (assuming that the data items it can store include other records and lists). Can you use a variable key name to call an item from an AssociativeList – like:
set keynameHolder to “blue”
set y to getItem(keynameHolder) of testRecord
I’m creating the record object myself, dumping data from Filemaker into the record which then needs to be parsed in Applescript. So I control all the keys and the structure of the record. And it doesn’t change after creation, and there are no application references. Data items are mostly strings and lists. I’m still hoping that the List and Record Tools osax might provide the magic bullet fix. The terrifying warning messages on your vanilla hacks page puts me off trying that solution!
Thanks again for all your help! I see that I have a lot to learn.
The only area where Ruby and Python can’t quite compete yet is in OSA component support (needed for attachability - folder actions, Mail rules, etc.), but they can completely replace AppleScript for anything else.
A library is a collection of general purpose subroutines, etc. stored in a script file which you can load into your own scripts in order to call those subroutines. The AppleMods libraries normally rely on the Loader library to do this loading for you. There used to be an installer provided for setting everything up, but the site is no longer actively maintained and the download page for that seems to have disappeared. If you want, you should be able to get the Loader library and install it manually; alternatively, you could just copy and paste the relevant sections of code from the Types library into your own script as the code is quite self-contained.
Correct. BTW, if your keys are all strings, the Dict object will be more efficient than the Associative List object.
You should be able to hack it with the List & Record osax, but as I say, records really aren’t intended for that sort of use and there are more appropriate data structures available, such as those provided by the Types library. Right tool for the job, etc.