• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: functions as sort of first class objects
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: functions as sort of first class objects


  • Subject: Re: functions as sort of first class objects
  • From: has <email@hidden>
  • Date: Fri, 27 May 2016 16:38:41 +0100

Mitchell L Model <email@hidden> wrote:

>> > On May 26, 2016, at 3:00 PM , has <email@hidden <mailto:email@hidden>> wrote:
>> > Subject: Re: functions as sort of first class objects

> I thank you I thank I thank you. That is one of the most — possibly the most — informed, clear, instructive, and helpful descriptions I’ve seen anywhere about all the topics you mentioned. [...] I have never understood the purpose or applicability of script objects and inheritance in AppleScr

If you know OOP then script objects and their delegation-based inheritance are what allow you to do a form of protoype-based OOP[1] in AS, should you ever build anything sufficiently complicated to need it. Unlike Smalltalk, Python, etc, AppleScript doesn't have 'classes', so there's no 'class vs instance' dichotomy: everything is just objects.

Closest familiar OOP analog is JavaScript, although it does *everything* by chaining new objects to existing objects - 'cloning' in JS merely creates creates a new _empty_ object that delegates to the 'cloned' object; there's no actual object copying as the term 'clone' might imply. OTOH, AS _can_ literally clone script objects using its built-in `copy X to Y` statement, but that performs an excessively deep copy that duplicates absolutely everything in the delegate chain, up to your top-level script and _everything_ in that, which unsurprisingly causes everything to bog down and break incredibly fast; so never do that. Instead, use a handler to construct new script objects by executing a `script...end script` statement:

    to makeWelcomingObject(salutationPhrase)
        script WelcomeObject
            to doWelcome(userName)
                say (salutationPhrase & space & userName
            end doWelcome
        end script
    end makeWelcomingObject


    set politeGreeting to makeWelcomingObject("Greetings")
    set casualGreeting to makeWelcomingObject("Hiya")

    politeGreeting's doWelcome("Bob") -- says "Greetings Bob"
    politeGreeting's doWelcome("Sue") -- says "Greetings Sue"
    casualGreeting's doWelcome("Bob") -- says "Hiya Bob"


Oh, you'll note in the above that the script object provides closure-style behavior, capturing the scope in which it was created (the `makeWelcomingObject` handler's stack frame). Which is another reason for never trying to treat handlers as native objects, because handlers aren't closures so any free variables they contain will break horribly and in completely bizarre and unpredictable ways the moment the handler 'object' moves to a different scope.

Script objects also provide the foundation for implementing library systems (e.g. my old AppleMods loader and AS's own 10.9+ library loader). And, of course, every script you write and run compiles into a script object, which can be serialized for storage to disk (or to send over IPC) and deserialized into a fresh script instance, so they're the foundation for AS's automatic, [almost] ubiquitous state persistence system as well (another Smalltalk influence, albeit on much smaller scale than mighty Smalltalk VMs). While not without its own shortcoming and defects they're actually one of AS's better ideas: just compare the mess of complexity in something like Python, which has 'class' objects and 'instance' objects and 'module' objects, and no intrinsic mechanism for persisting script state between runs. (Needless to say, I'm not at all shy about ripping off AS's best ideas for use in my own libraries and languages; and, of course, what NOT to replicate on pain of death.)


> It’s very difficult identifying undefined behavior in AppleScript, because everything in it is so weird that most of the time I either reuse and modify pieces of code that worked in another context or wander around until I get something working.

If a feature isn't listed in the official documentation (ASLG), then it's undefined.

Of course, even when a feature IS listed in the ASLG, there's absolutely no guarantee that the ASLG isn't lying its face off about what it actually is and how it really works. The AppleScript language lies like a pig in shit: all with the very best motives, of course - being simple and friendly and easy to use - but the problem is the language itself is actually heinously complex, and the right way to make a language simple and easy to use is to *eliminate* that complexity completely, not pretend to users that it doesn't exist.

For instance, ASLG never tells you that all the Apple event IPC stuff is actually RPC plus simple first-class relational *queries*[2], which is why 99.9999% of programmers absolutely despise and cannot understand AS: because AS syntax looks just enough like OOP that they naturally assume that's what it is, so are utterly flummoxed when it ups and does something utterly NON-OOPish on them. (And don't expect this ever to improve, because the AS team has repeatedly demonstrated that its answer to programmers failure to like, use, or support AS is to LIE EVEN HARDER TO THEM.)

Though to be fair to the original AS designers, some of the crap in AS is the unfortunate consequence of Apple mgt scrapping the original AS team the moment 1.1 went out the door, which meant a lot of problems that might've been identified and fixed early on never were; while other problems (e.g. the atrocious mess that is file paths and file system-related types and specifiers: alias, POSIX file, etc) are the unhappy result of trying to update or supersede original language features hamstrung by the technical limitations of System 7 without breaking existing code compatibility. (Particularly when the new additions aren't as rigorously thought through as they could be.) A lot of it though is just what you'd expect when programmers try to spelunk a previously unexplored and unfamiliar field in language design, and maybe don't have quite as wide a perspective on the topic (End-User Programming) as they really ought to.[3]



> In the process, unfortunately, as often happens with that kind of approach, is that I’ve built up mythical beliefs as well as kept mental pictures of things that have changed since I made them. One of the contributing factors is the minimalist approach the AppleScript documentation takes, though for what it is trying to do is actually very good. I think I read every AppleScript book that’d been published before about 8 years ago, but I don’t think any of them went into much sophisticated detail.

Your best bet is Apress's Learn AppleScript, 3rd edition, which I lead-authored. It still doesn't get into a lot of the really deep conceptual and technical stuff: I didn't say anything about application scripting being RPC+queries, for example, because the audience was wide and you gotta pick your battles. But one of the things I did include was a chapter about using script objects for doing libraries and OOP; the library stuff is pretty useless now that AS has its own native loader, but the OO stuff holds up (caveat a couple embarrassing errata, which I've already asked Apress to put on their site and they failed to do so, but I can email as a plain text file directly on request).



> What led to attempt this weird first-class object sort of thing — and gee, isn’t that what a script object is, duh? — is that I wanted to write a set of unit tests drive by a harness. Something like:

Been there, done that:

    https://github.com/hhas/applescript-stdlib

I've been remiss in getting that particular project finished off and properly distributed[4], plus the TestTools harness just happens to tickle a really wonderfully bizarre and utterly unpredictable bug deep deep in the AS implementation that periodically causes test scripts to fail in all kinds of really wonderfully bizarre and utterly unpredictable ways until you change a couple of characters at which point they suddenly magically work perfectly well, at least until the next code edit you make happens to set that damn bug off again. So if you want to write unit tests I recommend you just use that, and then slam me for inadequate documentation and examples till I motivate my lazy ass to fill in the remaining gaps.


> I realize this is pushing AppleScript a bit, but I was curious to see if it could be done.

Not at all. The language may suck, but it's "Turing-complete" as all the cool kids love to say about things[5], so you can write anything in it as long as you don't need to dive down to raw C calls to interact with external stuff, cos its FFI is various degree of limitations and suck. And don't mind it running slow as molasses, or falling down on stupid AS bugs, or generally drive you up the wall by being stupidly limiting and obtuse in how it lets you do it. e.g One time someone asked about writing a calculator in AppleScript <http://stackoverflow.com/questions/35538631/eliminate-hyphen-from-applescripts-text-item-delimiters/35539918#35539918>, and I obliged them.:) I just wouldn't _recommend_ it where you can help it: cos while all languages may be crap, using one that's even marginally less crap than AS will still save you a huge amount of time and frustration. Stick to using AS for desktop automation - which is the one thing it actually does right (and all the other official 'alternatives' do wrong) - and while you won't avoid pain at least you won't inflict even more than actually necessary.



> Anyway, thanks again for your wonderful post. I will change my code to use a script object forthwith.
>
> This came just in time, because I will be distributing the handlers with their tests soon to the Keyboard Maestro forum — the handlers actually call KM macros through KM’s AppleScript commands, so I can test the KM macros from this AppleScript. Each test puts starting text in a new TextEdit document, does stuff that involves calling one or more KM macros, gets the text of the doc, and compares it to the expected text. I will probably parameterize the initial text and expected resulting text too.

Tests are good. We should do more of those (not least the AS team itself!).

HTH

has

--

[1] OOP's just another tool that helps you manage growing complexity by organizing and packaging your code; basically the next step up from using libraries, which are the next step up from using handlers. If all your scripts are just quick 1-10 liners, of course, then it's not something you're very likely to need, of course.

[2] I strongly recommend reading the following paper by one of the original AS designers: <http://www.cs.utexas.edu/users/wcook/Drafts/2006/ashopl.pdf>. And for a more dev-friendly (albeit rough) summary of AE IPC: <http://hhas.bitbucket.org/understanding-apple-events.html>.

[3] AppleScript was derived from HyperTalk, which in turn draws much from Pascal because that was the standard teaching and production language for programmers back then; whereas what HT really should've been based on was Papert's Logo which, instead of trying to achieve simplicity through great cleverness and hidden complexity, achieved simplicity by _being simple_.

[4] Laziness, sickness, and the fact that this 'good deed' crap invariably takes twice as long as intended and doesn't pay a dime so real [potentially/actually] paying work needs to take priority. [6]

[5] Despite being neither old enough to have met a Turing Machine nor even appreciate what the damn phrase truly means and how it really isn't being helpful or meaningful at all.

[6] (Also the fact that having offered to turn the code over to Apple, lock stock and barrel, totally gratis no strings attached, the AS team can't even bother their asses to respond with so much as a "thanks but no thanks". 'Cos nothing says "We want our Users to love and use AppleScript" like an AppleScript team that gives every appearance of not giving a shit about either. So sue me, it's not my professional job to pick up after their crap.)
_______________________________________________
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


  • Prev by Date: Re: Folder actions
  • Next by Date: functions as sort of first class objects
  • Previous by thread: functions as sort of first class objects
  • Next by thread: functions as sort of first class objects
  • Index(es):
    • Date
    • Thread