📖
A General Introduction to Contextual Programming
  • A General Introduction to Contextual Programming
  • Chapter 1 - Thinking Contextually
    • 1.1 What is a Paradigm?
    • 1.2 What is Contextual Programming?
  • Chapter 2 - Creating Context
    • 2.1 Organizing Data
    • 2.2 Decorators
    • 2.3 Adaptation
  • Chapter 3 - Evaluating with Operations
    • 3.1 Hello World!
    • 3.2 Expanding on 'When'
    • 3.3 Operation Hierarchies
  • Chapter 4 - Reacting with Behaviors
    • 4.1 Revisiting Hello World!
    • 4.2 From 'When' to 'Whenever'
    • 4.3 Working with Buckets
    • 4.4 Expanding Purpose
    • 4.5 Adapting Behaviors
  • Chapter 5 - Abstracting Evaluations
    • 5.1 Compositions
    • 5.2 Operables
  • Chapter 6 - Abstracting Contexts
    • 6.1 Contracts
    • 6.2 Context Identifiers
  • Chapter 7 - Looking to What's Next
    • 7.1 Final Thoughts
    • 7.2 Additional Resources
Powered by GitBook
On this page
  • Overview
  • Aliasing
  • Extending
  • Excluding
  1. Chapter 2 - Creating Context

2.3 Adaptation

Overview

The first example of a context, Some Int :: Int : context., described itself as an adaptation. Adaptation is a type of for Contextual Programming. A context is primarily data being organized and presented in a manner most appropriate for the use of that context, so adaptation focuses only on enabling a context/record, called the descendant, to inherit the desired parts of another context/record, called the ancestor, and to present those parts appropriately for its use.

Adaptations have three primary aspects.

Aliasing

All adaptations are essentially a form of aliasing, which means an adaptation provides an alternative way to refer to something that already exists. In the first example, Some Int :: Int : context., the descendant's name, Some Int, is an alias of the ancestor, Int. An instance of one type as an instance of an aliased type.

The purposes of aliasing are to enable a context to be more specific to its use, to enable re-usability of code for related constructs, and to simplify conversions of data for different uses. All of these purposes can be seen with the Some Int example.

  • Some Int may be intended for specific use. The name, which is purposefully very meaningless in this example, could convey that use better than Int, which is widely used in most situations when a basic integer number is needed.

  • Some Int may be used in different scenarios than Int yet Some Int will maintain the same integer value as Int and can be used with all the same decorators in the same way (at least in how it is currently defined). However, the code for Some Int is very short, precisely because Int has already defined all of those decorators. This reduces how much code must be re-implemented for the same use.

  • Some Int is a context, whereas Int is not. This means they will have significantly different uses, but converting between them can be done easily because Some Int is essentially an Int by another name.

Not only can the types themselves be aliased, but the properties within them can be aliased as well. This can be seen with an alias for Position:

Other Position :: Position : context itself, new y [y].

In the above example, Other Position is an alias for Position and it has declared that a property new y will replace Position(y). new y is the same as y whenever the types are aliased between each other or whenever a decorator of Position refers to y and whenever a decorator of Other Position refers to new y. This kind of aliasing furthers the purpose first described above; for the descendent to be more suitable to its specific use.

Extending

Adaptations can go beyond aliasing to differentiating the capabilities of the descendant from the ancestor. One way this is accomplished is by extending the ancestor with new properties or by implementing different decorators. Looking again at building upon the Position example:

3D Position :: a Position with an Int for a third dimension: context itself, z;
    this matches Int, Int, and Int : x, y, z => 
        this(x) = x && this(y) = y && this(z) = z;
    -this : => 3D Position [ x[-this(x)], y[-this(y)], z[-this(z)] ];
    this + 3D Position : other => 3D Position 
        [
            x[this(x) + other(x)], 
            y[this(y) + other(y)], 
            z[this(z) + other(z)]
        ].

3D Position can be used as a Position with its x and y and all of its decorators, but it also defines a new z property and new decorators that are appropriate for working specifically with a 3D Position. It has extended Position's original properties and decorators with new ones that are better suited for its specific uses.

Excluding

Adaptations can also go in the opposite direction. Instead of extending an ancestor, they can exclude properties and choose not to reimplement decorators to limit the use of the descendant. This can be seen with a descendant of 3D Position:

Limited 3D Position :: a 3D Position that has no use for its x : context itself ![x].

In Rede, ! can be used with the stand-in notation to specify that there is no declaration name being defined for the stand-in property. The declaration will proceed to fulfill its intended purpose, in this case replacing x, but the result will not be identifiable or referenceable in the current .

Limited 3D Position can be used the same as a 3D Position but whenever it is known as a Limited 3D Position the x property will be unavailable. The actual x property and its (default) value exist but are excluded from any use with the Limited 3D Position. This is another way that adaptation enables descendants to take on a form that is most appropriate for their specific use.

Previous2.2 DecoratorsNext3.1 Hello World!

Last updated 6 months ago