Actions, part 4

The last topic to cover in this series concerns Action parameters. There are several basic categories of Action parameter; which one is most appropriate depends on how the Action is used. In turn, the category used may have consequences on how the Action is invoked.

The strictest category forces parameters to a specific Model. At the other extreme, the generic category allows any type of parameter. Intermediate categories restrict inputs to a class of types.

The following Action definition illustrates several input categories:

@@foobar
>>  *() a
>>  *(a) b
>>  *int c
>>  *list d
<<  *(@) e = (@foobar)

The *() definition allows any type of object; there are no restrictions. Parenthesis in BOOL indicate a reference to some object; by definition, an empty reference is a generic reference to an object of dynamic type. (A given object’s type never changes, but references can change to refer to other objects.)

The *(a) definition is also dynamic in that the actual type isn’t known until run-time. This definition does constrain that type to be the same as the object a‘s type. The name in the parenthesis (the name being referred to), can actually be almost anything, although most names have a static type that don’t require a run-time reference.

An exception is @foobar‘s return object, e, which is set to be a reference to @foobar itself. The return object type is explicitly a reference to an Action. Without the parenthesis, the object’s type would be an actual Model, named “@” (and of course no such Model exists — Actions are a meta-type).

The third definition, *int, requires the input parameter to be an Object instance of the *int Model, or a Model that emulates it. Models that sub-class the *int Model are also legal parameters. Essentially, the Action asks, “Are you an *int instance?” If the object responds positively, it passes.

[There are some risks in a Model that allows itself (its instances, actually) to be treated as if it were another Model. Violation of the user’s expected behaviors is one. Failing to handle a Message it should is a another.]

The *list definition constrains the input to be a List, which has some implications for the caller. Specifically, the input must be a list. In a situation where there is only one item, it must still be on a list.

For example, a @print definition might have a header like this:

@@print
>>  *list items
<<  *int n = length:items;

The single input parameter is (required to be) a List. (For one thing, this insures that the length: Message gets a sensible answer.)

A common way this Action might be invoked is like this:

@print a, b, c, d

Which would print the values of objects a, b, c and d. The comma-separated list creates an implicit list. The explicit form is:

@print = a, b, c, d

(Remember, the equals-sign (=) indicates a List in BOOL.) So long as there are multiple items — and therefore commas — an implicit List is fine (and cleaner). But to @print a single item, the List must be explicit:

@print = a

You can also use the multi-line List form:

@print
=   really-really-long-object-name
.   another-very-long-object-name
.   hyphens-are-legal-in-BOOL-names

Again, the equals-sign is optional (always optional in this explicit form).

The situation is identical to initialization Lists for Object instances. They must always be a List, even if there is only a single initialization value (which is almost always the case — which seems to make the syntax a bad idea, but something is necessary to differentiate an initialization value from an object that happens to come next).

For example:

*int answer = 42

Again, to stress that the equals-sign is not an assignment operator. It signals the beginning of an explicit List. The multi-line form is available here, also:

*string message
.   "Now is the time for all good people to party!"

And here you see exactly why a List is required. A List implies (usually) a kind of ownership to the object “above” it. Most Lists are preceded by something that “owns” it. In this case, the Instance object “owns” any List that follows and considers it to contain initialization values.

By the way, the multi-line form is especially handy with arrays:

*array *string
=   "Apples are red (when they're ripe),"
.   "And blueberries are bluish and sweet."
.   "You might think my little poem rhymes,"
.   "But it doesn't"

(Sorry.)

Advertisements
%d bloggers like this: