Nagle suggested a "post-mortem" on Hypercard in the World as it currently is, to discuss what worked well and what didn't. I'd like to do that at some point. In the meantime, I thought I would write a brief description of how the system currently works.
---
Hypercard in the World is a world of physical objects with virtual attachments.
In order to participate, an object must be blessed, which provides it with an identity.
It can then have attachments added. Attachments can describe:
- physical state (e.g., where it is: "location in container"; or the trio "location in camera", "location in display", "physical size")
- virtual state ("variable", "collection", "file")
- behavior ("daemon", "illumination")
---
Objects can be inspected through the web-based inspector:
In the left column, you see that the "hit-test root objects" object has a "location in container" attachment and a "daemon" attachment.
Selecting an attachment in the left column lets you edit it in the right column. There are different types of editors for different types of attachments. In the screenshot, you see a daemon attachment being edited with a code editor.
Attachments are viewed live, so if (for example) an object is changing a variable, you can watch that change simply by inspecting the variable attachment.
---
Hypercard in the World is "built in itself", in the sense that the identities and attachments of all objects are represented by values which themselves live in collections on physical objects.
At the left, you see the "identities" and "attachments" objects. The "identities" object holds a collection whose values look like:
{ id, name, family, selection_mode }
The "attachments" object holds a collection whose values look like:
{ id, object_id, type, ... } (where "..." is specific to the type of attachment)
Blessing an object simply means adding a value to the "identities" collection. Unblessing simply means removing this identity, as well as associated attachments. (Blessing and unblessing by hand is normally done through the inspector.)
There are no databases at this level of abstraction.
Underneath, all collections are stored in one big Seatbelt database. Sometimes I used to create additional databases for special purposes, but that was cheating and I found I mostly didn't need to do that.
In scripts, there is a Javascript API for accessing and querying collections, which looks like:
db.find(collection, query)
db.get(collection, id)
db.set(collection, id, value)
etc.
The "db" prefix was a bad choice, because it misleadingly blurs the abstraction boundary. Early mockups referred to state with tokens instead:
I couldn't find a reliable way to implement tokens in the code editor.
The API is also awkward because it only deals with values in collections. There is no API for working with identities, variables, etc. Instead, you read a variable by looking it up in the meta-level "attachments" collection. I kept it this way to avoid adding layers of opaque "helper functions" until I better understood what was needed -- the principle was to keep things as transparent as possible, so you stayed in touch with what was really going on.
What I should have done was add the helper functions anyway for the game jam etc., recognizing that no raw Javascript API could provide the desired transparency without being awkward, and simply looking ahead to when we could get away from raw Javascript.
On Jan 17, 2016, at 3:20 AM, Toby Schachman wrote:
Here are a few ideas about organizing state in the new system.
In the current Room OS, there are two levels of state. There's the database and then on top of this the "hypercard-y" bits of state on objects (Variables, Attachments, ...).
In our next system, it seems like we want all state to live on objects. Whether or not there is a database that makes this work is behind the abstraction boundary. Such a database would not be exposed by the system.
In Hypercard, all state (properties) and behavior (scripts) are "attached to" or "live on" an on-screen object (card, button, text field, etc). In Apparatus, all state (attribute values) and behavior (attribute expressions) live on a shape. In both, you can pull up an inspector to see or edit any of this state.
<image.png>
<image.png>
I was inspired by Bret mentioning on Friday how he wants to be able to laser a camera and then see what the camera is seeing. What the camera sees is virtual state, so it needs to live on an object. And what better object for it to live on than the physical camera itself.
Here is a mockup of inspecting a webcam:
<image.png>
Here's what inspecting the lion in the Serengeti might show you:
<image.png>
You see all the virtual state as a list of properties. Values are shown as their visualization (as in previous email). You can use (reference) any of these values within expressions, as in Apparatus/DDV. Or you can reference objects in scripts and change their properties when events happen, as in Hypercard/Smalltalk.
I feel like this simple model can take us very far. Just inspect a few objects--use as many inspector boards as you want, we've got all this space!--then hook the data together like in Apparatus or Hypercard.
The hooking together is easy. Generally Hypercard scripts and Apparatus expressions are short. You get rich behavior by setting up rich relationships between objects.
Virtual state encompasses:
- In data: image the camera sees, what keys are pressed down on the keyboard, the accelerometer data on the wiimote.
- Out data: brightness level of the LED, image the screen should show, image the printer should print, angle the servo should go to.
- Variables: angle the frog's eyes should be looking at, mole game time remaining, laser socks "health level".
- Attachments: lion's roar sound, mole image, Whole Earth Catalog's page images. (Attachments are essentially constant variables.)
- Behavior definitions: expressions that evaluate, scripts that run.
All of this state would be accessible and editable in a uniform manner by inspecting the object it lives on.