2.2 Decorators
Overview
Contexts are primarily structures of data, but those data need to be checked for whether they qualify for operations/behaviors, and new contexts should be able to be produced, at least in part, from existing contexts. Decorators offer an optional way to meet both of these needs for any given context. Contextual Programming defines the following two types of decorators, although a language may .
Qualifiers
Qualifiers offer a way to query whether a context qualifies for an operation/behavior, in language appropriate for the purpose of the context. The result of a qualifier will always be a . If the result is 'true', it can be said that the context 'qualifies'. How qualifiers are used is shown when operations are covered in more detail.
In general, a qualifier can be declared, within a context, following :
this "text with optional 'type name' for parameters":
'parameter names, as needed' => "logic that evaluates to a boolean"
'this' is a keyword when used in this kind of declaration. It represents the context itself and must be the first word of a qualifier.
A Parameterless Example
A simple, parameterless, example building upon a context declared earlier:
Some Int :: Int : context;
this is even : => .
Equality in Rede is checked for using a single '='. This aligns more with the symbol's use in mathematics and is different than many languages, which often use double equals, '=='.
An Example with Parameters
An example with parameters, again building upon a context declared earlier:
Position :: a 2D location represented by Int and Int : context x, y;
this matches Int and Int : x, y => this(x) = x && this(y) = y.
The 'x' and 'y' in "(x, y)" are associated with the two Ints in the qualifier's declaration description. As with the context declaration, parameters in this way match, by order, with the types in the description.
Operators
A common operator that most people are familiar with is '+', the addition operator. As with many programming operators, it has its roots in mathematics, and like its use in mathematics, it takes two (being in math) and produces a new instance. Operators in Rede work much the same way.
A Parameterless Example
There are operators that do not take another instance. A prime example being . Looking again at the Position context from earlier, there's an opportunity to add a negation operator. The below example adds an operator to do so:
Position :: a 2D location represented by Int and Int : context x, y;
this matches Int and Int : x, y => this(x) = x && this(y) = y;
-this : => Position
[
x[-this(x)],
y[-this(y)]
].
With this operator declared, negating a Position with code such as -some position
will provide an expected and appropriate result.
An Example with Parameters
The Position example can be extended again with an operator that takes a parameter, like so:
Position :: a 2D location represented by Int and Int : context x, y;
this matches Int and Int : x, y => this(x) = x && this(y) = y;
-this : => Position [ x[-this(x)], y[-this(y)] ];
this + Position : other => Position
[
x[this(x) + other(x)],
y[this(y) + other(y)]
].
Now a Position can be added to another Position through code such as some position + another position
, with the result being the actual addition of those two Positions.
Last updated