# 6.1 Contracts

## The Purpose of Contracts

Contracts are another mechanism of abstraction, this time over the data types. Any record, context, enum, operable, or composition type can be bound to a contract. A contract can be used in any operation or behavior, in place of any type that is bound to it. This enables an operation/behavior to depend upon a contract (or set of contracts) instead of a specific type.

The logging feature can be improved upon with contracts to show how this mechanism is useful.

## Contracting Contexts

Recall the logging feature as it was [last implemented](#user-content-fn-1)[^1]:

```
App State :: defines the state of the app through a Bool : context
    continue running [True];
    this is shutting down: () => not this (continue running).

Log Level :: Int : enum
    Verbose[0],
    Debug[1],
    Warning[2],
    Error[3].

Log Settings :: logging settings with Log Level : context
    minimum level [Log Level (Debug)].
    
Log Message :: a String message and a Log Level, to be logged : context
    itself, level [Log Level (Debug)].

Console Log Route :: Log Settings : context.

Run App :: create the default App State, initialize and run until shutdown :
    behavior {app}?
    
    Initialize :: for {app} when initialized?
        activate Log Message ["App Initialized.", Level [Log Level (Debug)] ];
    
    Run :: for {app} whenever app(continue running)?
        activate Log Message ["App is running.", Level [Log Level (Verbose)] ],
        evaluate Console Response,
        activate Log Message ["About to shut down!", Level [Log Level (Warning)] ],
        app(continue running) is False;
    
    Shutdown :: for {app}
        whenever app is shutting down,
        after all?
            deactivate app.

Maintain Console Log Route ::
    maintain the existence of an optional coexistent Console Log Route in accordance 
        with shared App State : behavior {route, app}
            when app(continue running)?
        
    Log Stop :: when terminated?
            activate Log Message ["Stopping Logs.", level [Log Level(Debug)] ].

Perform Route Logging :: 
    handles logging per a unique Console Log Route for shared {*Log Message*} : 
        behavior {route, messages}
        where messages is messages filtered by
            [(message) => message(level) >= route(minimum level)]?
    
    Valid Log Message :: Log Message : context;
    
    Initiate Logging :: for {messages} 
            whenever |messages| > 0, 
            foreach message in messages?
                evaluate message as Valid Log Message,
                deactivate message.

Perform Console Logging [Perform Route Logging] ::
    logging per a unique Console Log Route for shared {*Log Message*}: 
        behavior {route, messages}?
        
    Log :: log a Valid Log Message to the console : <message>?
        evaluate "Log: \(message)" as Console Message.
```

There are a couple of areas where this implementation can still be improved. The first is in the re-use of `Perform Route Logging`. As is, `Perform Route Logging` would need a different implementation for every type of log route, like `Console Log Route` or `File Log Route`, even though its functionality has been abstracted away from any specifics for that context, so one contract that will be needed is for log routes.

Another is the dependency on the specific context type of `Log Message`. There's nothing wrong with `Log Message` itself, but every time a log is created with anything but the default `Log Level`, the `Log Level` must be specified. For something as commonly used as logging, that can end up looking a bit clunky. The deactivation in `Perform Route Logging (Initiate Logging)` is a bit odd as well. The deactivation of the message may be better handled by a behavior more dedicated to that purpose.

Focusing on the former, the first step is to create the new contract:

```
Log Route :: a logging route with a Log Level : contract context 
    minimum level [Log Level (Debug)].
```

Next, `Console Log Route` can be updated to specify that it is bound to the contract:

```
Console Log Route [Log Route] :: 
    a log route to the console with Log Settings : context.
```

Notice the use of the stand-in notation, `[ ]`, to specify that `Console Log Route` can stand-in for `Log Route`, which results in the declared type (`Console Log Route` in this case) being bound to the contract (`Log Route`). Since contracts are automatically fulfilled, with `minimum level`, `Log Settings` no longer serves a purpose, so it can be removed:

```
Console Log Route [Log Route] :: a log route to the console : context.
```

{% hint style="warning" %}
Fulfilled, as used above, means that all of the values and decorators specified in the contract will automatically be added to the bound type. However, they will only be accessible through the contract[^2]. The values can be explicitly defined in the bound type to make them accessible through the contracted type as well, or they can be replaced, but they cannot be removed. If there is conflict in values provided by two contracts, then at least one of them must be replaced in the contracted context if the context wants to provide access to both.
{% endhint %}

{% hint style="danger" %}
Contracts and ancestors serve different purposes in Contextual Programming.

An ancestor is like a starting point for a type [to adapt](https://rede.gitbook.io/a-general-introduction-to-contextual-programming/chapter-2-creating-context/2.3-adaptation#overview). A descendant can be used where an ancestor is required (they can be cast to one another), but descendants do not automatically qualify for behaviors/operations that require the ancestor type. Ancestors are also inherited; a descendant, `B`, of `A`, will pass on its adaptation (or lack thereof) of `A` to its own descendant, `C`. Furthermore, a descendant can only have one ancestor.

A contract specifies how a type can be used. In the example of the logging feature, `Console Log Route` can be used anywhere there is use of `Log Route`, including for the qualification of a behavior or evaluation of operations. Since a descendant could potentially break a contract fulfilled by its ancestor (by removing a value), contracts must be explicitly declared for each non-contract type (they are not inherited from an ancestor). However, a type can be bound to multiple contracts.
{% endhint %}

To address the latter concerns outlined earlier, `Log Message` can be re-implemented as a contract with new contexts that fulfill it:

<pre><code>Log Message :: a String message to be logged per a <a data-footnote-ref href="#user-content-fn-3">constant</a> Log Level : 
    contract context
    <a data-footnote-ref href="#user-content-fn-4">itself</a>, 
    level [Log Level (Debug)].

Verbose Log Message [Log Message] :: <a data-footnote-ref href="#user-content-fn-5">a verbose log message</a> : context
    <a data-footnote-ref href="#user-content-fn-6">level</a> [Log Level (Verbose)].

Debug Log Message [Log Message] :: a debug log message : context
    level: [Log Level (Debug)].

Warning Log Message [Log Message] :: a warning log message : context
    level: [Log Level (Warning)].

Error Log Message [Log Message] :: a error log message : context
    level: [Log Level (Error)].
</code></pre>

One more layer of abstraction will be useful for a generalized approach to deactivating the log messages. This will be started by specifying that the `Log Message` contract itself is bound to a high-level `Message` contract, like so:

```
Message :: contract context.

Log Message [Message] :: a String message to be logged per a constant Log Level : 
    contract context
    itself, 
    level [Log Level (Debug)].
```

{% hint style="warning" %}
A contract bound to one or more contracts is effectively a descendant contract inheriting from its ancestor contract(s), but it is actually fulfilling any such contracts on behalf of its own fulfillers. As such, any non-contracts bound to a contract will inherit the requirements of that contract, including its bound contract(s). In effect, with the current example, a `Debug Log Message` fulfills the `Log Message` contract, and in doing so, fulfills the `Message` contract. However, contract descendants cannot remove anything declared by their bound contract(s), a stipulation that enables this form inheritance between contracts.
{% endhint %}

A `Message` at this high-level isn't concerned with whether there is a specific value being conveyed as the message, so much as it is just specifying that the contracted type will be handled, behaviorally, as a message.

{% hint style="info" %}
Programmers familiar with Object-Oriented Programming, at least as it is implemented in some languages, might see similarities in contracts with a concept called interfaces. They are similar in purpose and use (respective to the differences of the two paradigms), with the primary difference, at least in Rede, being that contracts are not inherited by non-contract types like interfaces are, which is to accommodate the more flexible adaptation of non-contract descendants.
{% endhint %}

## Abstracting Behavior Contexts

With the contracts in place, the behaviors can be updated. This is done by simply replacing the contexts with their stand-in contracts, like so for `Perform Route Logging`:

<pre><code>Perform Route Logging :: 
    handles logging per a unique <a data-footnote-ref href="#user-content-fn-7">[Log Route]</a> for shared {*[Log Message]*} : 
        behavior {route, messages}
        where messages is messages filtered by
            [(message) => message(level) >= route(minimum level)]?
    
    Valid Log Message :: [Log Message] : context;
    
    Initiate Logging :: for {messages} 
            whenever |messages| > 0, 
            foreach message in messages?
                evaluate message as Valid Log Message,
                deactivate message.
                
</code></pre>

{% hint style="warning" %}
Notice how `Valid Log Message` is now a descendant of `[Log Message]`. It isn't a descendant of the contract itself in this case, but a descendant of any type that fulfills the `Log Message` contract, such as the `Debug Log Message` or `Verbose Log Message`. This enables any of those contexts that fulfill `Log Message` to be cast and evaluated as a `Valid Log Message`, without the cast explicitly knowing about the contracted type.
{% endhint %}

The points at which log messages are created and activated must also be updated to use the new contexts:

```
Run App :: create the default App State, initialize and run until shutdown :
    behavior {app}?
    
    Initialize :: for {app} when initialized?
        activate "App Initialized." as Debug Log Message;
    
    Run :: for {app} whenever app(continue running)?
        activate "App is running." as Verbose Log Message,
        evaluate Console Response,
        activate "About to shut down!" as Warning Log Message,
        app(continue running) is False;
    
    Shutdown :: for {app}
        whenever app is shutting down,
        after all?
            deactivate app.

Maintain Console Log Route ::
    maintain the existence of an optional coexistent Console Log Route in accordance 
        with shared App State : behavior {route, app}
            when app(continue running)?
        
    Log Stop :: when terminated?
            activate "Stopping Logs." as Debug Log Message.
```

That's much cleaner looking now, and it would be easier to find where all log messages of a certain type are coming from, if that were helpful for debugging.

Finally, the message deactivation can be addressed. Having the high-level `Message` contract introduces a concept to this application, that being the Messaging Pattern. This pattern outlines how contexts can serve as messages, that is, a fleeting notification to be handled by various behaviors before an expected destruction. With this pattern, any context can fulfill the `Message` contract to become a literal message upon activation, passing through its behaviors before it is deactivated. There may be variations where a message persists longer than a single stream's evaluation, or where the message-like functionality is more conditional, but this simple implementation works for this use case.

The only real work that needs to be done is a behavior to deactivate messages, as the last functionality to occur for any message's activation stream:

```
Cleanup Messages ::
    deactivate all messages, {*[Message]*}, after their evaluations: {messages}?
    
    Scheduled Message :: [Message] : context;
    
    Initiate Cleanup :: for {messages}
        whenever |messages| > 0,
        foreach message in messages?
            evaluate message as Scheduled Message;
    
    Deactivate :: deactivates a Scheduled Message : <message>
         after all?
             deactivate message.
```

`Cleanup Messages` will be created when the app runs, for an empty bucket that exists to catch any activated contexts that fulfill the `Message` contract. Once activated, upon reactive evaluation, the `Initiate Cleanup` will run and effectively schedule any messages to be deactivated after all of that specific context's other operations have completed.

While unlikely, it is possible that a message could be scheduled multiple times for deactivation. If this weren't using a bucket and a new behavior was created for every message, then that wouldn't be the case, but this persistent behavior offers better performance. This issue is actually an opportunity for additional functionality to this application's concept of a message.

To start, the `Message` contract can include a new value:

```
Message :: a message with a Bool indicating if it is scheduled to be deactivated :
    contract context
    will be deactivated [False].
```

This new value, `will be deactivated` can serve as a flag for whether the message has been scheduled:

```
Cleanup Messages ::
    deactivate all messages, {*[Message]*}, after their evaluations: {messages}
    where messages is messages filtered by 
        [(message) => not message(will be deactivated)]?
    
    Scheduled Message :: [Message] : context;
    
    Initiate Cleanup :: for {messages}
        whenever |messages| > 0,
        foreach message in messages?
            message(will be deactivated) is True,
            evaluate message as Scheduled Message;
    
    Deactivate :: deactivates a Scheduled Message : <message>
        when message(will be deactivated),
        after all?
             deactivate message.
```

Now any scheduled messages will be excluded from `Cleanup Messages` bucket of messages and won't be scheduled again. It also enables messages to have their deactivation delayed (one stream's evaluation) before they occur, by setting `will be deactivated` back to `False`. That might be useful in some situations, although it won't be useful for the logs. By default, that value is hidden from the logs, when used as `Log Message` or any fulfilling contexts, so attempting to influence that value isn't possible without enabling it explicitly.

[^1]: At least the version of it that will be used going forward.

[^2]: Another bound contract using the same value name and type will provide access to that same value as well.

[^3]: `constant` declares a value as being a constant. It cannot be set during creation of the context or changed afterwards.

[^4]: A contract that specifies `itself` will require any fulfilling type to have an ancestor of the type of `itself`. This is true if `itself` is also implicit in the contract and can be fulfilled implicitly in the fulfilling type.

[^5]: The required `String` ancestor is implicit through the automatic fulfillment of `Log Message`.

[^6]: `level` is available through the automatic fulfillment of the `Log Message` contract. Its purpose here is to replace the default constant value specified in the contract, however, it is not defining or replacing the `level` property itself, so it will not be made available outside of the context's use as its contract, `Log Message`.

[^7]: The stand-in notation here signifies that the behavior will be working with any fulfilling type of the contract and not an instance of the contract itself, which cannot actually be created. This is consistent syntax with how contracts are used anywhere outside of their own declarations.
