Dimensions and Rituals
In this tutorial I'll cover the core feature of EDPP and Aetherlang - Dimensional programming. Basically, it's a way of doing computations in parallel. In case you are interested in technical details of implementation of dimensions in Julia version of Aetherlang, you should read the source code. I can only say that it was originally built on multithreading.
Block Syntax
The syntax of dimensions may look unfamiliar for lispoids (those coding in Lisp). However, it is very simple and, to my mind, much clearer than adding another layer of parentheses (sorry, lispoids, no offense). It was basically the first thing I could think of when making my first notes on dimensional programming so I've decided to stick to this simple design.
@ imagine that we import some libraries here
@ creating simension D0
dim D0
dim D1
...
enddim D1
dim D2
...
enddim D2
@ wait for subdimensions
dimwait :D1
dimwait :D2
enddim D0
A natural question arises: if dimensions are meant to be executed in parallel, how will this code run? The code above will first push "main" dimension into execution list as it is where everything happens by default (as, say, in the C Programming Language where you should wrap your program into the "main" function). Inside this main dimension, which you can consider our main routine, we then have "dim D0" line that tells the interpreter to form a new dimension with its end being at "enddim D0", label it "d0", and put it onto execution list. Main dimension then skips all this D0 block and since we don't have anything after it, main exits. But our program won't fully stop until all dimensions exit, while we still probably have D0 on our list. By this time it has probably already created D1 and D2 dimensions and awaits them to then finish.
Subdimensions and Namespaces
Another question that you should ask at this point is about namespaces. If a nested dimension (subdimension) is executed in parallel with its parent dimension, what is with their namespaces? Do they share some names? Yes and no.
use :base
use :io
@ create dimension Δ1
dim Δ1
@ name A is in Δ1
A = 5
@ create dimension Δ2
dim Δ2
@ name A was copied to Δ2 from Δ1; name B is defined in Δ2
B = A
enddim Δ2
dimwait :Δ2
C = B @ ERROR: name B was not defined in Δ1
enddim Δ1
Interacting via the Ether
How can we then interact between dimensions? Well, all of the dimensions are, formally speaking, executed inside ether. Ether is also omnipresent in any dimension, function, or ritual. Technically though, that simply means you have access to ether variable namespace wherever you write your code. This namespace is dynamic and united (meaning that there's only one ether and its names at any given point are the same for all dimensions). Syntax details on defining names in ether were described here. So, to share data between dimensions you simply put it into ether and expect it to be accessible from elsewhere. A useful thing in such cases will be "aetherwait"
Rituals
Rituals are essentially the same as dimensions but they rave no names, they cannot be nested, and, most importantly, they are infinitely looped. Interpreter does not wait for them to end to finish the program entirely.
@ imagine that we import some libraries here
@ creating a ritual
ritual
...
endrit