4.1 Revisiting Hello World!
Last updated
Last updated
Behaviors are constructs that provide additional meaning to their required, and qualifying, contexts, with encapsulated operations that can to changes in those contexts. The contexts associated with a behavior form a relationship that can be leveraged by the behavior and other behaviors/operations, . This reactivity and the conditional associations between contexts and their shared operations is at the heart of Contextual Programming, enabling programmers to more effectively develop dynamic applications.
Before going over the internals of a behavior, it's best to understand how a behavior exists and what to expect of it. Behaviors require contexts that have been "activated". So far, there have been no such contexts explicitly activated. Doing so can be done with this generalized syntax, within an operation, :
All contexts can be activated. Once this is done, a behavior that requires a context of the same type as the activated context can evaluate it to see whether it qualifies to be associated with the behavior and its other contexts, that is, if all of its required contexts exist and qualify. In some cases, multiple instances of behaviors can exist.
An instance of a behavior may be similar to an instance of an object in Object-Oriented Programming, although there are some differences. A behavior will be instanced, meaning it will exist with specific associations and will perform its functionality, if its context requirements are met. Once a behavior has its requirements met, any additional contexts (that cannot be associated with that behavior based on ) will be considered for additional behavior instances.
When a behavior can no longer continue to exist as an instance, namely because one of its contexts were . Then the remaining contexts are (usually, again depending on how its defined) considered for new behavior instances with other contexts that are currently in-use with other behaviors. This highlights one of the primary differences in instances, compared to Object-Oriented Programming, that being the internal data of a behavior instance may persist and be associated with a new behavior instance automatically.
Although, if a context enters a state in which it will no longer qualify for any behavior that either already exists or that can be immediately created, then it will be deactivated automatically and removed from memory once it is no longer in use by any evaluating operations.
One of the most basic behaviors is one that was, unknowingly, being used back in the . That code was:
There's no apparent activation occurring here, but the operation that handles Console Message
will actually activate the Console Message
and a Console Output
context. Afterwards, a behavior that works with a Console Output
context and any activated Console Message
contexts will append each value of those Console Messages
to a Messages
property of Console Output
. The Console Messages
are deactivated at a later time through another behavior to prevent unnecessary memory use. As part of the console's refresh cycle, any content in Messages
of Console Output
will be printed onto the console.
As described, that's quite a bit happening behind the scenes. The purpose of reducing all of that down to evaluate some string as Console Message
is to simplify the steps taken to output to the console, and to prevent the need to make Console Output
a required context for any number of behaviors/operations. However, there may be times when it is appropriate to declare and activate Console Output
directly, and to have it as a .
In addition to other useful properties, Console Output
has the aforementioned Messages
property. The value of this property is exactly that which appears in the console to the user, including the user's , although word wrap to fit within the bounds of the console may change how it appears. Every message is assumed to be its own print statement, with an assumed at the end. Having direct access to this property is useful, as the contents of the console can be cleared by changing that property to be an empty list, or otherwise altered.
The Hello World! example can be updated, based on the generalized syntax to activate a context, to explicitly declare Console Output
, like so:
On the third line, activate output is Console Output
is performing an inline declaration of a Console Output
called output
, then activating it. This provides output
for further use while also activating it so the console printing behavior mentioned previously can be initialized and begin working.
This example can be shortened further by setting messages
at the point of output
being declared:
This code is similar, but output
is no longer named in the declaration, as it isn't needed beyond its activation, and the Console Output
instance is initialized with messages
set to "Hello World!"
, as is accomplished with the code Console Output [messages ["Hello World!"]]
.
The opposite of activating is deactivating, which informs the runtime that the previously activated context (if it was activated, if not, nothing happens) should no longer be active. Any behavior that was depending on the context will no longer have access to that context, so if its existence was required for the behavior to function, then the behavior will be terminated, and any relationships formed between other contexts due to that behavior are broken.
Deactivation is done in the same manner as activation, :
Knowing that Console Output
will update the console display with its contents if it is activated, then it can be expected that the console won't continue to update if Console Output
is deactivated:
The above code will deactivate output
, after the first two messages are printed, which will prevent the console printing behavior from outputting the last message, as would have happened once the operation completed. Besides that, there are a couple of new concepts in this code.
The keyword itself
is seen when updating the value of output(messages)
. When used as part of an itself
refers to the value being assigned to. It's a shorthand, in some cases, to updating a value that changes with reference to its previous state.
The second is await
. While there is a comment in the code describing what that line is doing, it's worth noting that in general await
will allow any pending reactive evaluations of the subsequent context(s) to occur before this operation continues. In this specific case, the only pending reactive evaluation is the console printing behavior updating the display for the change to messages
as shown in the line directly before await
.
The last line, output(messages) is "Hello World!"
is assigning a single String
to the list of messages
in output
. This will result in messages
being a list with one item, the String
that is Hello World!
. This change will the console printing behavior to update the console's display, resulting in Hello World!
being displayed to the user.