Skip to content

Commit

Permalink
Merge pull request #128 from Phuire-Research/UI
Browse files Browse the repository at this point in the history
Data Oriented Functional Inheritence
  • Loading branch information
REllEK-IO committed Oct 29, 2023
2 parents 3b85f4e + 815f3cb commit 6362241
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 31 deletions.
50 changes: 50 additions & 0 deletions DataOrientedFunctionalInheritance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Data Oriented Functional Inheritance
This can be considered to be the true goal of a Unified Turing Machine. This was the original intention with this framework back in 2018 I was referring to this as a nTuring Machine. Was a method of creating functional libraries with the ability to inherit functionality in the same way that object oriented libraries. If you are familiar with functional programming, then the majority of what you have access to are tools that enable for the programming style. Versus the sweet of libraries made available to objected oriented. And run into difficulties where functional programming acts more like glue than concrete when formalizing applications. Even "RxJs," while considered functional, its core design utilizes constructors and object oriented inheritance between different modes of functionality.

Each time you wish to implement one feature from that object, you inherit everything else that comes with it, even if you are attempting to have just one slice of that functionality. Thus the solution towards creating a function means of sharing libraries was finding a means of allowing for functionality to be composed. Enter "Concepts," and their "Qualities." Where qualities are groupings of shared functionality that transform a shared data type. Where the state of the "Concept," acts as methods of controlling the how and what is being transformed.

As all data transformations in this system are stateless if taking place solely within the "Method" of your "Concepts." The reducer is merely acting as a signal as to when to prompt for the next step in this system. As "Plans" observe these signals. Alterations to the state inform the how and what is being transformed.

# Unification over Inheritance
```typescript
export function unifyConcepts(
concepts: Concept[],
emergentConcept: Concept
): Concept {
let newConcept = createConcept('', {});
forEachConcept(concepts, (concept => {
newConcept = unify(newConcept, concept);
}));
newConcept = unify(newConcept, emergentConcept);
newConcept.name = emergentConcept.name;
return filterSimilarQualities(newConcept);
}
//Unification under the hood.
base.qualities = [
...base.qualities,
...target.qualities,
];
```
Notice the simplicity of what is happening within the unifyConcepts function. That we are using the order of the passed array to formalize a stacked base of concepts to be unified together. Alongside a final emergent concept that enhances the qualities of these concepts to be utilized together. This is likewise a form of compositional dependency. To guarantee that your concepts will always have the required qualities necessary to perform their functionality.

As functionality is not defined solely by the Actions that each "Quality" describes. But their utilization within an ActionStrategy. In the current form of Stratimux, what is missing is a final compilation that determines the exact strategies utilized within your application. Once this is implemented, not only are you inheriting functionality in the same manner of object oriented programming. But the functionality that is not currently being utilized within your application can be pruned. As "ActionStrategies" effectively map the entire operation of your application. This would be accomplished via its own set of concepts that formalize a proper interface to interact with this non-linear method of functional programming.

What is interesting to note within this system is likewise the ability to directly inherit plans via your concepts principles. That you can have a base server concept that expands itself. Via a compositional quality of tried and tested implementations. Such as attaching a static endpoint to a server, database, and user interface. As this likewise affords for those individual units to be load balanced and separated into their own processes.

The difference between Object Oriented Programming. And this Data Oriented Functional approach. Is that functionality itself can exist within a solved state and that is what is composed. Versus the recomposition of objects to again formalize a concept that is simply being redesigned over and over again. The majority of applications that exist, are nothing more than catalogs with an item view.

Therefore what this system is seeking to do. Is to not just be the store, database, and user interface to access a catalog. But the creation and orchestration of the catalog itself. As each item within the catalog is likewise composed of concepts. What this method of programming is proving is that this is a logical fact. Something that can be described in programming and tested to formalize any application or thing in existence.

As everything is just data. And data is merely the most important qualities that we have written down. What we are as people are transformers of that data and this system of programming is merely the method of transforming using the basest form of abstraction. Concepts. To perform those transformations.

# Accessing your Unified State and Functionality
```typescript
export function selectUnifiedState<T>(concepts: Concepts, semaphore: number): T {
return concepts[semaphore].state as T;
}
```
This directly relays to the functionality within your "Methods" and "Principles." As by default your Reducer is already based its state upon each successive call. What is orienting the state of your concepts is the same universal concept of spacial location that actions use to call their qualities within Stratimux. This "selectUnifiedState," merely accesses the concept as it is loaded into the Axium. And is handled automatically within the provided helper method functions. Thus the only true place where this would need to be implemented by the developer is the principles themselves, which also are supplied the current location by semaphore in that creation function.

Therefore this allows for each of your concepts to have their own counter functionality, but this likewise limits the implementation of Unified Concepts. That these concepts are only functional via their principles due to the guarantee of a supplied concept semaphore. As such, when creating actions or strategies for a "Unified Concept." Be sure to supply this value to the necessary action creator or action node.

The benefit of this approach. Is that we can determine responsible concepts that only function only via its internal specification, including being responsible for its spatial location within any loaded Axium. Allows for these responsible concepts to be "Unified" without worry of interacting with "Concepts" that may use some functionality it others would depend upon. Therefore the "Axium" can be seen in current terms as a "Composition of Applications" that have a shared interface that is the "Axium" itself.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The inspiration for Stratimux was that of Redux and its origin via the FLUX desi
* [Action Controller](https://github.com/Phuire-Research/Stratimux/blob/main/ActionController.md) - Allows methods to be performed asynchronously.
* [Spatial Ownership](https://github.com/Phuire-Research/Stratimux/blob/main/SpatialOwnership.md) - Streamlines the complex nature of the ActionStrategy as it relates to itself and other axiums. This is what allows Stratimux to be a graph computation paradigm.
* [Strategy Data](https://github.com/Phuire-Research/Stratimux/blob/main/StrategyData.md) - Allows for the ActionStrategy pattern to act as a "Universal Transformer." Likewise decorates strategies with the necessary information to inform "ActionNodes," of possible failure conditions.
* [Data Oriented Functional Inheritance](https://github.com/Phuire-Research/Stratimux/blob/main/DataOrientedFunctionalInheritance.md) - Proving the "Unification of Concepts," as a method of "Functional Inheritance."
* [Unified Turing Machine](https://github.com/Phuire-Research/Stratimux/blob/main/The-Unified-Turing-Machine.md) - The governing concept for this entire framework.

## The Halting Problem
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@phuire/stratimux",
"version": "0.0.54",
"version": "0.0.55",
"description": "Unified Turing Machine",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
60 changes: 36 additions & 24 deletions src/model/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type ActionType = string;
export type Action = {
type: ActionType;
semaphore: [number, number, number, number];
conceptSemaphore?: number;
payload?: unknown;
strategy?: ActionStrategy;
keyedSelectors?: KeyedSelector[];
Expand All @@ -28,30 +29,38 @@ const createPayload = <T>(payload: T) => payload;

export function primeAction(concepts: Concepts, action: Action): Action {
const expired = action.expiration < Date.now();
let semaphore: [number, number, number, number] = [-1, -1, -1, -1];
if (!expired) {
const conceptKeys = Object.keys(concepts);
for (const i of conceptKeys) {
const index = Number(i);
const semaphore = getSemaphore(concepts, concepts[index].name, action.type);
if (semaphore[2] !== -1 && action.expiration) {
let axium;
if (action.axium) {
axium = action.axium;
} else {
axium = (concepts[0].state as AxiumState).name;
}
const newAction = {
...action,
semaphore: semaphore,
axium,
};
if (newAction.strategy) {
newAction.strategy.currentNode.action = newAction;
if (action.conceptSemaphore) {
semaphore = getSemaphore(concepts, concepts[action.conceptSemaphore].name, action.type);
} else {
const conceptKeys = Object.keys(concepts);
for (const i of conceptKeys) {
const index = Number(i);
semaphore = getSemaphore(concepts, concepts[index].name, action.type);
if (semaphore[2] !== -1 && action.expiration) {
break;
}
return newAction;
}
}
}
if (semaphore[2] !== -1 && action.expiration) {
let axium;
if (action.axium) {
axium = action.axium;
} else {
axium = (concepts[0].state as AxiumState).name;
}
const newAction = {
...action,
semaphore: semaphore,
axium,
};
if (newAction.strategy) {
newAction.strategy.currentNode.action = newAction;
}
return newAction;
}
const badAction: Action = {
type: axiumBadActionType,
payload: createPayload<BadActionPayload>([action]),
Expand Down Expand Up @@ -137,7 +146,8 @@ export function createAction(
payload?: unknown,
keyedSelectors?: KeyedSelector[],
agreement?: number,
_semaphore?: [number, number, number, number]
_semaphore?: [number, number, number, number],
conceptSemaphore?: number
): Action {
const special = getSpecialSemaphore(type);
const semaphore = _semaphore !== undefined ? _semaphore : [0, 0, -1, special] as [number, number, number, number];
Expand All @@ -153,21 +163,23 @@ export function createAction(

export function prepareActionCreator(actionType: ActionType) {
return (
conceptSemaphore?: number,
keyedSelectors?: KeyedSelector[],
agreement?: number,
_semaphore?: [number, number, number, number]
qualitySemaphore?: [number, number, number, number]
) => {
return createAction(actionType, undefined, keyedSelectors, agreement, _semaphore);
return createAction(actionType, undefined, keyedSelectors, agreement, qualitySemaphore, conceptSemaphore);
};
}
export function prepareActionWithPayloadCreator<T>(actionType: ActionType) {
return (
payload: T,
conceptSemaphore?: number,
keyedSelectors?: KeyedSelector[],
agreement?: number,
_semaphore?: [number, number, number, number]
semaphore?: [number, number, number, number]
) => {
return createAction(actionType, payload, keyedSelectors, agreement, _semaphore);
return createAction(actionType, payload, keyedSelectors, agreement, semaphore, conceptSemaphore);
};
}

Expand Down
10 changes: 8 additions & 2 deletions src/model/actionStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { KeyedSelector } from './selector';
* @param failureNode - `optional` ActionStrategy.failed() will fire Axium Conclude Type if left blank or set to null.
* @param payload - `optional` Will set the payload of the action.
* @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore().
* @param conceptSemaphore - `optional` Used for Unified Qualities. Must be specified via that principle's passed semaphore value.
* @param agreement - `optional` Is time in milliseconds of the actions intended lifetime.
* @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows.
* @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList.
Expand All @@ -29,6 +30,7 @@ export interface ActionNode {
action?: Action;
actionType: ActionType;
payload?: unknown;
conceptSemaphore?: number;
keyedSelectors?: KeyedSelector[];
semaphore?: [number, number, number, number];
agreement?: number;
Expand All @@ -43,6 +45,7 @@ export interface ActionNode {

export interface ActionNodeOptions {
keyedSelectors?: KeyedSelector[];
conceptSemaphore?: number;
semaphore?: [number, number, number, number];
agreement?: number;
decisionNodes?: Record<string, ActionNode>;
Expand Down Expand Up @@ -200,6 +203,7 @@ export const strategySuccess = (_strategy: ActionStrategy, data?: Record<string,
nextNode.keyedSelectors,
nextNode.agreement,
nextNode.semaphore,
nextNode.conceptSemaphore
);
nextNode.action = nextAction;
nextNode.lastActionNode = strategy.currentNode;
Expand Down Expand Up @@ -268,7 +272,8 @@ export function strategyFailed(_strategy: ActionStrategy, data?: Record<string,
nextNode.payload,
nextNode.keyedSelectors,
nextNode.agreement,
nextNode.semaphore
nextNode.semaphore,
nextNode.conceptSemaphore
);
nextNode.action = nextAction;
nextNode.lastActionNode = strategy.currentNode;
Expand Down Expand Up @@ -348,7 +353,8 @@ export const strategyDecide = (
nextNode.payload,
nextNode.keyedSelectors,
nextNode.agreement,
nextNode.semaphore
nextNode.semaphore,
nextNode.conceptSemaphore
);
nextNode.action = nextAction;
nextNode.lastActionNode = strategy.currentNode;
Expand Down
6 changes: 3 additions & 3 deletions src/test/actionController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { axiumLog, axiumLogType } from '../concepts/axium/qualities/log.quality'
import { createActionNode } from '../model/actionStrategy';

test('ActionController Expired Test', (done) => {
const act = axiumLog(undefined, 200);
const act = axiumLog(undefined, undefined, 200);
const cont = new ActionController(act);
cont.subscribe(action => {
expect(action.type).toBe(axiumBadActionType);
Expand All @@ -13,7 +13,7 @@ test('ActionController Expired Test', (done) => {
});

test('ActionController Next Test', (done) => {
const act = axiumLog(undefined, 200);
const act = axiumLog(undefined, undefined, 200);
const cont = new ActionController(act);
cont.subscribe(action => {
expect(action.type).toBe(axiumLogType);
Expand All @@ -23,7 +23,7 @@ test('ActionController Next Test', (done) => {
});

test('ActionController createActionController$ Test', (done) => {
const act = axiumLog(undefined, 200);
const act = axiumLog(undefined, undefined, 200);
const cont = createActionController$(act, (controller, action) => {
controller.fire(action);
});
Expand Down
2 changes: 1 addition & 1 deletion src/test/ownership.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test('Ownership Test', (done) => {
// Will be ran after both counting strategies conclude.
const ownership = selectState<OwnershipState>(cpts, ownershipName);
console.log('Stage 2', ownership.ownershipLedger, ownership.pendingActions);
dispatch(counterSetCount({newCount: 1000}, undefined, 7000), { iterateStage: true});
dispatch(counterSetCount({newCount: 1000}, undefined, undefined, 7000), { iterateStage: true});
},
(cpts, dispatch) => {
const ownership = selectState<OwnershipState>(cpts, ownershipName);
Expand Down

0 comments on commit 6362241

Please sign in to comment.