Behavior is Content's better half. A good picture can keep one's attention only so long. But when the Animation Queen shimmies and sways, beckoning you to the dance, time loses all meaning.

Acorn's goal here, as always, is to make it easier for world builders to enliven their world of things, so they can:

This chapter does not explain how to do all those things (that requires a book or two), but it does talk about how Acorn makes them possible. In essence, we want Acorn to make it easy to describe how things change over time, guided by events and state. More particularly, we want Acorn to facilitate a helpful separation of concerns between the world and its parts:

Again, the specifics of how to accomplish that is covered elsewhere. But when we look deeply into those needs, we can derive the essential capabilities Acorn must have to make such behavior possible:

Methods are Behavior

In many others languages, the facilitator for behavior is functions, which are typically free agents. They swim in a vast sea of many functions and are bound to specific data only when called.

In Acorn, the facilitator for behavior is always (and only) the Method. Every behavior, every action, is completely accomplished through the use of one or more Methods. Unlike functions, these Methods are rarely self-less, free agents. The elegant versatility of the Method stems from the intriguing ways it is often bound to other values before and when used:

Let's explore each of these ideas further.

Parts and Their Methods

In Acorn, most methods belong to a type or part. It is done this way so that every value can establish its library of methods, each of which represents a different action to perform with/on that value. Such methods specify 'self' to refer to the value they are working with/on.

Thanks to multiple inheritance, this design is driven from the bottom: by the needs of the part. Each part cooks its own library, simmering into the stew the methods from its type, methods from various mixins, and methods unique to the part itself.

This method-within-part modularity brings several benefits:

Methods ❤ State

Acorn provides many different ways for methods to be married to a specific state. We have already discussed one of them: the part, which packages its property state with the interface methods that can be used to access or change the part's state.

The closure combines state and methods in a very different way. It tightly binds together a small, private list of values to one or two Methods. The result is a single value that can be used wherever a Method can be used. It has several great uses:

The three types of executable context (yield, thread and process) provide yet another way to package state with methods into a single value. A context's stack holds not just private values (like a closure) but also the entire execution state, including all active methods it is in the middle of performing. Contexts serve diverse purposes:

Note: Due to Acorn's commonly-used techniques for pre-binding Methods to a state, state machines can be straightforwardly implemented within a single part, closure or yielder. Typically, all state names would be represented as symbols. The 'match' statement would be used to handle the state machine dispatch to the appropriate logic. Alternatively (with parts), one could even use the state symbol to directly dispatch to the part logic defined by the same-named method.

Group Intelligence

There are certain types of parts we might call controllers. They are more than collections: their methods coordinate activities across their client parts. Each controller generally has a narrow focus for the work it coordinates, such as:

As parts are created, they can subscribe to specific controllers, specifying the help they wish to receive. Once controllers know who their clients are, they can make use of each clients' properties and methods as needed to accomplish their work. Usefully, a part's mixins or types can automate this subscription and supply whatever properties and methods are needed to facilitate the handshake with the controller. Acorn's dynamic, late-binding nature makes such dependency injection easy to perform.

Controllers help separate concerns between a world and its parts. Controllers are typically attached to a world for easy accessibility by client parts, thereby extending the world's generic functionality. Responsibility for the controller's work is managed by the controller, with the work apportioned appropriately between the controller and its client parts.

Active Variables and Properties

Acorn makes it possible for pre-arranged method(s) to be performed every time a specific variable or part property is retrieved (get) or changed (set). To anyone using the variable or property, it looks like it only holds a value. But under the covers, the defined methods (typically provided by a get/set closure) are performed whenever the variable or property is touched.

Using a closure, it is also perform something like a "super" override, incorporating any previously-defined methods into a newly added method. The closure would simply capture the old value or method as a closure variable, and then invoke it at the appropriate point in the new method.

The ability to instrument variables and properties with hidden methods can be very valuable, as it enables:

Event-driven Worlds

In order to faithfully render animated, interactive 3-D worlds, these worlds must be good at detecting and handling events. Once a world's content is loaded, it runs its main loop over and over. Many times every second, the main loop:

  1. Looks for and handles user interaction events (keyboard, pointer, touch, etc.). These are delegated out to all affected parts for handling.
  2. Updates the scene's state, effectively animating it. This is accomplished by sending an event signal to every part (or controller) that wants to update its state.
  3. Renders the scene 3-D parts and 2-D widgets (with their help), synchronized to the display's refresh rate.

Any part can receive and send events, not just the world. Controllers typically do both. Importantly, parts can be wired to send an event signal to another part whenever the value of specified, computed properties change. This capability can be used to implement two-way binding between some part and on-screen widgets used to view or change that object's properties.

Acorn provides several ways to communicate various types of event to a part:

This straightforward technique for event handling depends on all participating parts accomplishing their triggered tasks quickly, particularly when a single event triggers a cascading sequence of actions. If event handling takes too long (e.g., when loading content resources), the world will stop and stutter. Such lag problems can often be ameliorated by spinning time-consuming work to threads.

Summary

At first glance Acorn's behavioral facilities seem too humble to discuss, as all behavior is performed by the simple, stateless Method. However, it is the many different ways that a Method can be dressed up with state information that makes Acorn versatile enough to gracefully model the complex, modular behavior of a 3-D world.

_