<< >> Up Title Contents


4.7 Miscellaneous Issues


4.7.1 Shallow vs. Deep Cloning

A question arises when a box is cloned about which of its internal parts should be cloned along with it. For example, in the case of an actor with no complex internal parts, there is no need to clone any of its slots--the values will be inherited. But if the actor has sensors, the sensors need to be copied so that the new creature has its own perceptions, rather than inheriting those of its parent! So, in some cases internal parts do need to be cloned. Which objects require this treatment? Ordinary slots, in general, do not need to be copied by this mechanism, since their values are inherited. The objects that need to be copied explicitly are those that cause some side-effect, such as creating an image on the screen (actors) or compute a value based on local information (sensors). LiveWorld provides a mechanism that allows any box to specify that it must be cloned whenever a box that contains it is cloned. Such boxes are flagged with an internal annotation, %copy-as-part. Whenever any box is cloned, all of the original box's annotations are examined via recursive descent for the presence of this flag, which if present causes the box containing it to be cloned into the appropriate place. Since the appropriate place might be several levels deep in the new box, the intervening container boxes must also be cloned.

The same mechanism is used to maintain dynamic inheritance relationships after an object is cloned. For example, if turtle-1 is cloned to form turtle-2, and then turtle-1 is given a sensor, turtle-2 should receive a clone of that sensor. The %copy-as-part flag also controls this propagation.

4.7.2 Internal Frames

LiveWorld uses annotations to record information about its internal functioning (for example, the screen position of a frame's display is stored as an annotation on that frame). Showing these to the user would be confusing. LiveWorld therefore allows certain frames to be marked as internal, with the result that they are not normally displayed to the user in the box view or in menus. The convention used is that internal frames are those whose names begin with the % character[16]. An advanced user can choose to display these frames, by holding down an additional key during a command that opens a box or displays a menu. A frame with its internal frames exposed may be seen in Figure 4.16. Internal frames serve some of the same purposes as closets do in Boxer.


Figure 4.16: A box that has (some) of its internal frames showing. One of them, %view-size, also has its own internal frames visible. The values in these slots are Lisp point objects that denote x-y coordinate pairs.

Aside from the display information shown in the figure, internal frames are used to store data for internal mechanisms like demons, internal state like interestingness (see 4.4.6), and slots whose value would be meaningless to the user, such as pointers to Macintosh sound objects.

4.7.3 Deleting Boxes

Deleting objects can be problematic in a prototype-based object system. One issue is the question of how to deal with objects that inherit from the object being deleted. Framer's built-in handler for deletion simply disallows deletion of a frame with spinoffs. LiveWorld extends Framer by allowing the user to specify a way to proceed when a problematic deletion is detected. The user's options are to:

Splicing out a frame involves removing it and its annotations from the inheritance chain so that it may be deleted. Each spinoff of the spliced-out frame (and its annotations, recursively) must have its prototype changed to point to the prototype of the spliced-out frame, and if the spliced-out frame provides a value that value must be copied into each spinoff. This complex-sounding procedure retains the old values of slots and retains as much of the inheritance relationship as is possible. Giving the user choices is fine for interactive use, but does not deal with the problem of deletion by a program in a live simulation. For instance, in a dynamic biological simulation, animals will reproduce by creating spinoffs of themselves. If a parent is eaten by a predator, we don't want the child to be affected, but we also don't want the system to stop and ask the user what to do.

There are also some fundamental problems with splicing out prototypes. Consider the case where there is a prototype ant, and many spinoffs of it (and possibly spinoffs of the spinoffs). Say further that there is an anteater in the simulation with an ant sensor. Sensors often specify the type of object they are sensitive to. If the prototypical ant gets spliced out and deleted, the ant sensor will be pointing to a deleted frame. Even worse, the ants will have no common prototype that allows them to be considered to be a class of objects[17]. Furthermore, the ants now each have their own copy of whatever properties were defined by the prototype (such as the complement of sensors and agents) so it is no longer possible to change these characteristics without changing them individually for each ant.

A better solution to the deletion problem, which makes good use of LiveWorld's hierarchical structure, is to keep prototype objects in a separate theater (see Figure 4.17). These prototypes are then outside of the simulation, inactive, and so in no danger of being deleted.


Figure 4.17: Illustrating the use of a separate theater to hold prototypes.

The deletion problem is one that is not found in class-based object systems, where there is no danger that the definition of a class of objects will be taken as an element of that class. Some other prototype-based object systems, such as Self (see section 4.9.2) avoid this problem by using static rather than dynamic inheritance. In Self, spinoffs inherit properties from prototype at the time they are created and do not maintain a pointer back to their prototype, so deleting the prototype is not problematic.

4.7.4 Install and Deinstall Protocol

LiveWorld defines an install/deinstall protocol on frames. Whenever a frame is created, deleted, or moved it is sent :%install and :%deinstall messages as appropriate (a move will generate both). Methods for these messages handle operations such as installing demons for computed slots or creating the graphic representation for actors.

4.7.5 Error Handling

Any programming environment must be able to deal with unexpected conditions. LiveWorld utilizes Common Lisp's condition handling system to provide an error handling facility with a box-based interface. When an error is detected, it generates a Lisp condition object which is then encapsulated into a box. For any type of error, the system can provide specialized error boxes that provide user options or other information.


Figure 4.18. An error has occurred in the execution of the trail-rule method, generating the error object no-method-error.

An example is shown in the figure. The error box contains three buttons that specify restart options. Clicking the create button, for instance, causes a method object of the appropriate name and type to be created, after which the user can fill in its slots.


[16] It would be more elegant to use an annotation to convey this information. The % convention is an artifact of LiveWorld's development history, and has been retained for reasons of efficiency.

[17]It might be argued that using prototypes to specify classes is a bit inelegant anyway. If the sensors were truer to their real-world models, they would not specify a type of object to be sensitive to, but instead would use a detectable characteristic of the object (i.e. the ant sensor would look for objects that were small and black). This is certainly implementable within the framework of LiveWorld, but would be considerably less efficient than the current scheme.


<< >> Up Title Contents