HyperCard and PL as powerful but hard to use interface

In the past few months I've thought about HyperCard some, in the context of an app that would use a high granularity fiber-VM implemented with coroutines as continuations. Imagining fiction-based docs about such a VM, I supposed one character might decide "I want to clone HyperCard" and then look at issues from that perspective. One reason this is interesting is because HyperCard downplayed exactly what happened in terms of time-order when events were processed: objects executed HyperTalk scripts in response to event stimulus like mouseUp, and other events. In principle these might run in parallel with each other — except Mac apps at the time rarely exposed concurrent semantics, and no way to coordinate via locks to avoid interference was provided in the language.

(I see a daemon-based implementation, with the UI in another process that is just viewer, frontend, and editor, so you can expose both a browser interface and native widget app UI at the same time for the same daemon runtime. This would include remote shell connections to run scripts in the daemon the same way you could run commands in HyperCard from a little message dialog box. The main disadvantage with this model is that you can write really unpleasant things with it, like distributed fork bombs, that you can't stop end users from deploying. In other words, it would be easy to be evil, which gives me moral qualms. The last time I said this to a coworker months ago, he said what people do with tools I write is not my problem.)

As an excuse to talk about HyperCard, I'm using a Hacker News discussion to source an interesting remark from Programming Languages are the Least Usable, but Most Powerful User Interfaces (uw.edu) (Andrew Ko).

In the top comment as of this moment, HN user jasonwatkinspdx supposes:

If the hypercard model had the value I think it does, someone else should have surfaced and gained momentum.

I especially like suppositional reasoning, so this sort of remark is one I enjoy. A reply I have in mind writing here (if anyone likes this topic) has at least two parts: 1) what would happen if someone deployed an updated HyperCard style tool, and 2) how folks pursue options in tech that yield max personal advantage rather than intrinsically useful basic infrastructure.

Unless someone does so first, later I'll quote a paragraph from Andrew Ko's original piece: the part about value of text programming languages in contrast with graphical user interfaces. I want to keep this first post short, as a seed for discussion, if any. I'm more interested in the programming language angle — how does a runtime behave and how does this model appear in the language — than I am in the business model of an app, which is off topic here. Also completely on topic is Andrew Ko's original blog post (same as the HN link above).

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

No problem, I'll just go back to what I was doing.

It's okay no one is interested. I have a similar lack of interest in what most folks find engaging (web apps), so it's only fair. Apps built around web sites have a central authority with narrow interests, so users can't really do much but march to the tune played by an authority. Forums, like this one, permit folks to talk but not do much else, so maybe it doesn't seem limiting since talking only does so much anyway.

My main interest in a fiber-VM daemon is simulating distributed network loads by generating actual network loads, but with a lot of control over nuances of timing, sizing, and stream transformations. (This isn't interesting to many folks.) But simulating something and actually being that thing are hardly different if performance and costs are the same. So it's feasible to turn something oriented toward simulation into a production tool, especially if it performs as well or better than existing code, for parts that have been compiled to good native code.

Here's that paragraph I mentioned. Andrew Ko writes:

There are other usabil­ity heuris­tics for which pro­gram­ming lan­guages might even sur­pass the usabil­ity of their graph­i­cal user inter­faces. For exam­ple, what user inter­face bet­ter sup­ports undo, redo, and can­cel than pro­gram­ming lan­guages? With mod­ern text edi­tors and ver­sion con­trol, what change can’t be undone, redone, or can­celed, at least dur­ing design time? Our best pro­gram­ming lan­guages are also per­haps the most con­sis­tent, flex­i­ble, min­i­mal­ist, and beau­ti­ful user inter­faces that exist. These are design prin­ci­ples that most graph­i­cal user inter­faces strug­gle to even approach, as they often have to make sac­ri­fices in these dimen­sions to achieve a bet­ter fit with the messy real­ity of the world.

I'm not sure I agree with the point about undo and redo, given a reasonable document framework with an undo model. But it seems simpler with text, and easier to verify with simple tools managing checksums.

Apple in the early 90's was very anti text command line, to the extent any desire to use a scripting language was politically incorrect, even if this meant inferior reproducible automation for testing. Only graphical user interfaces were good. If you wanted a text-based script, you were bad. At least among folks working on Pink.

More on HyperCard

I was on the HyperCard team until '92, when the writing was already on the wall re: Apple. HC had a remote script invocation scheme that worked over AppleTalk, we used it to write some multi-player games which we used in house. Before I left I demoed to Scully HyperTalk enhancements I made that allowed for real-time control of HyperTalk stacks running on different machines connected via AppleTalk and/or MIDI. Statements such as:

run this every 3 seconds
run this after that
run this after that every 3 seconds
run this at 10:30:12

were valid HyperTalk statements (provided that this and that were bound to scripts). Remember OS9 was not multi-tasking or multi-threading, I did this all with interrupts and posting to the main event loop when necessary. These changes never made it into release but maybe they did make it into AppleScript, I don't know. As to why simple (like wiki) but powerful (not like wiki) tools have not surfaced, I really don't know.

Nice script examples

Nice to hear from you. The HyperCard team was starved when I started on OpenDoc storage around '94. I was still on Pink in '92. (I spent '93 on a graphical programming language on NeXT boxes elsewhere, because an Apple hiring freeze stopped OpenDoc from growing.) Calhoun was still there, but I never saw other HC devs around.

I like the way your HyperTalk examples are about time, when I said HyperCard mostly ignored timing. :-) Those are good examples of dense features expressed crisply. That language didn't have much punctuation. I prefer more when it reduces ambiguity. Both HyperTalk and AppleScript were able to parse in ways not obvious to me, following some do-what-I-mean default I had trouble seeing. I like languages with a do-exactly-what-I-say focus instead.

When I kept saying I wanted to write scripts, Pink devs said "go talk to the AppleScript folks" because they were open to that. But when I talked to AS devs, and asked what features were built into the language, they said it depended on what was supported in a given app. It was like AppleScript had a latent grammar, but no actual words. In the abstract, it was like a set of human interface guidelines for how an app would do AppleScript, along with infrastructure and api for parts actually present. But very little was built-in, and I didn't see how it helped me. When I threatened to port a Unix style shell to Pink, I was blocked more actively than mere stone-walling. Command lines were evil, according to gospel, because devs had adopted the mantra preached to end users.

I've written prototypes of fiber scheduling in single-threaded network appliances for asynchronous deduplication backed by local disk caches, so to me it's clearly possible to make something like HyperCard fully concurrent inside without multi-threading, via coroutines and cooperative multitasking. But it's hard to get by without threads when api is not async. On the old OS9 architecture it would probably necessary to put worker queues in another process to make blocking system calls. It'd be a mess. Today things are much simpler, when it's easy to spin up a thread pool to service blocking operations.

One thing I loved about HyperCard was how you could open a widget and browse and/or edit its script. After that I wanted every user interface to have widgets you could open to see what they did, then perhaps request docs explaining expected usage. But instead of more visibility and transparency, I saw less as the 90's progressed. Undiscoverable UI features were especially aggravating. When I asked Netscape Navigator devs how I was supposed to learn a feature was possible, they said, "By watching someone else," as if all normal people approached learning software as a social experience. Loners were like witches.

We're getting off-topic

Hi Rys,
Let's take this off-line, I don't think any one else is interested in our reminiscing! I'm trying to remember you, did you work for a bit on System 7 sound? my email is dahvid.minor at gmail.com. I did speak with Calhoun a few months ago.

PL as UI

I'm very interested in PL as user interface.

I discussed this in a recent manifesto, which describes how an IDE & PL with certain characteristics (fine-grained sharing, live programming, generation of programs for user actions, extraction of programs from user's action history, first-class user-model) can become a suitable life-long UI. I also wrote a few blarticles: UI as an act of programming, Programming with augmented reality, and Ubiquitious programming with pen and paper (and AR) that each touch on aspects of unifying UI with PL. Tacit programming with arrows, hands, and zippers also discusses the utility of a first-class user-model in programming.

My Awelon project is also oriented towards this goal. It has a long way to go. I believe there are a lot of "you can't get there from here" issues, where aspects of modern language design tend to greatly hinder their use as a UI. These can only be addressed through new substrate languages, which is the intention for Awelon bytecode.

The second coming of HyperCard

As somebody who cut my teeth on HyperCard (yes, I'm that young/old, depending on your perpsective), I've often wondered what an "updated" HyperCard might look like, and why no obvious contender has surfaced.

One trap that I think many people fall into is looking at the "cards" themselves as a fundamental feature or HyperCard, while I would claim that they are just a highly visible superficial feature. Cards just happened to be a parsimonious choice of metaphor:

  • Sequences of cards were a common method for storing and organizing information in that era: people still had Rolodexes, and libraries still used card catalogs.

  • Cards were also able to capture the screen/form-oriented model of many line-of-business applications, so that they naturally matched a common way of looking at and thinking about UI.

In each of these cases, I would argue that in a post-Internet-ubiquity world, these arguments in favor of cards as a metaphor fall flat. Projects that tried to replicate HyperCard by replicating the card-ness of it were doomed to fail.

The more fundamental values in HyperCard were things like supporting WYSIWYG and direct manipulation together with code-behind, blurring the line between run-time and edit-time, a lightweight database, and a good match between the standard components/behaviors and what users typically needed.

In this regard, I'd argue that the most visible successors to the legacy of HyperCard are:

Wikis A wiki can be seen as taking the "card" concept and replacing it with "pages," thus creating something of a mid-point between HyperCard and the larger Web. It is unfortunate the Wikis largely dropped the code-behind scriptability and lightweight database angles, but it seems like there might be an obvious advancement to be made there. When I look at something like a Wiki guide for a game, I see a lot of tabular data there that screams to be integrated together into a database abstraction.

Game Engines Go spend some time with the toolsets for Unreal or Unity, or even just go and play with Little Big Planet or other games with in-engine editing, and you'll see a lot of direct manipulation, blurring of run- and edit-time, and combinations of visual/hierarchical construction and code-behind.

This isn't to say that I don't think a more direct successor to HyperCard could be made; I would just argue that we might not have an easy time recognizing it as such.

more or less agree...

Well, no one seems to be demanding a HyperCard clone. To me a hypothetical HyperCard clone is an excuse to motivate examples of writing app runtimes using cooperative multi-tasking, in the form of fibers that look like Unix processes all running in one address space (with pipes, standard input and output, and simulated file system that can be mirrored to an actual file system or whatever else seems handy, like an in-memory store that persists to tar archives that you can explode to examine). This would also resemble a clone of MPW with respect to command line tools, if you only care about cooperative scheduling in one address space.

Architecture is hard to convey outside argument and discussion form, because many possible paths exist through trees of options. So I thought it'd be simpler in docs to present design as arguments and discussion among fictional characters. A reader might find backtracking discussion easier to follow when it corresponds to characters returning to earlier trains of thought, or persisting in focus despite interruption, side-discussion, rabbit-holing, and bike-shedding. A character named Ty wants to clone HyperCard, but others don't really care — except everyone is happy to criticize. :-) A character named Wil is doing the VM runtime, and he'd like a frontend UI for interacting with a backend daemon, and whatever Ty pursues is okay as long as it's not too crazy.

So I'd be inclined to write fictional devs telling Ty the HyperCard idea is no good, for various reasons including ones you note. Why copy an old thing when many new alternatives exist? For example, Wil intends to have the daemon service a port with HTTP, so he can browse daemon state with a browser. This would include Ty's runtime for HyperCard running in the daemon, using web pages as prototypes of cards. Every HyperCard object could have at least one unique URL, to browse each part separately. Or you can write scripts to slice and dice things any way you want to interact with the app's model of an object system.

(End users, who are not primarily developers by trade, might find a constrained HyperCard style interface easier to understand than Wil's approach to opening a shell in the daemon to inject whatever user interface he wants in a browser.)

Whatever Ty ends up with, it wouldn't really be HyperCard, no matter how much he says parts resemble the original model. For example, suppose Ty and Wil settle on Lisp syntax for scripting. Is that like HyperTalk? No way, but Ty may say it's pretty close. (Don't think of Ty as a rational actor; his full name is Tyler Durden.)

The card metaphor is not strictly necessary, though it makes sense to retain the idea of top-level viewable entity, the same way a browser typically presents URLs as pages. The main idea is that these contain smaller UI elements, which delegate events to cards if not handled by smaller UI widgets. And cards delegate unhandled events to a background, etc. The model is really an event-handling hierarchy to process messages in a scoped manner.

When you say "successor to HyperCard", it sounds like a product. What if instead you had a library of utilities in a toolkit, which resembled HyperCard when assembled one way, or something else entirely when assembled another way. Wil and his buddy Ned want to embed the VM runtime inside another product, where it implements network appliance plugins. But a headless embedded component is hard to debug and drive in testing, unless you run a peer in another process, which talks to the embedded instance. In fact, Wil wants to implement network stack plugin prototypes entirely inside host simulations, just for debugging purposes, before migrating to the real production environment. Ty's HyperCard work-alike could be a testbed frontend in development, while Wil's primitive HTTP server reveals statistics for ops monitoring when enabled. Who cares whether someone makes a product around the tools?

Ty's position — let's clone HyperCard — is a strawman argument. I agree with you an end result might not be recognized as the same thing, since slavishly hewing to the original plan would seem a waste of time. And it would be more fun to have something like a blend of wikis and game engines instead: some kind of nasty distributed concurrent scripting chimera.