Having spent the week being chased by project management over deadlines, I’m relaxing this weekend by trying to get my head around a programming language called “Whenever”. It’s a language that has no variables, no flow control, and not even a fixed execution order. All you can be sure of is that statements will be executed… eventually. Somehow it fits my mood.
Whenever has line numbers but these are only used for statements to reference each other, they don’t set an order of execution. After executing each statement the interpreter removes it from the listing and picks the next statement to execute at random.
When a statement is executed it can evaluate a boolean to decide whether to defer
its execution, or can execute and then list itself to run again
at some later time.
In the following program if line 1 is randomly picked by the interpreter it will execute and print an “N” and then disappear from the listing. When line 2 is picked for execution it will evaluate whether line 1 is still in the listing. If line 1 is still present then line 2 will defer
itself to later execution.
So lines 1 and 5 will execute at random times, while 3, 4, and 5 will each defer
themselves until a specific statement has executed.
$ cat newt.we
1 print("N");
2 defer (1) print ("e");
3 defer (2) print ("w");
4 defer (3) print ("t");
5 print ("*");
In fact lines 3, 4, and 5 will keep deferring themselves until after line 1 has executed. Line 1 and line 5 execute at random so we eventually get N e w t
output, but with the asterisk appearing at a random place in the output.
$ ./whenever newt.we
*
N
e
w
t
$ ./whenever newt.we
N
*
e
w
t
Apart from the asterisk appearing at a random position the code is non-deterministic in the sense that you can’t predict how many times that lines 2, 3 and 4 will execute before they output their characters.
In the following listing line 1 evaluates a boolean (whether line 3 is still in the listing) and if true
it adds another copy of line 4 to the listing. So as lines 1 and 2 are randomly executed they will add additional copies of lines 3 and 4 to the code. As an instance of line 3 or 4 is executed and outputs its message it is removed from the listing. Eventually all the copies of lines 3 and 4 will be executed and removed and the program will halt as there are no more statements to execute.
$ cat frog.we
1 again (3) 4;
2 again (4) 3;
3 print ("Ribbit!");
4 print ("Croak!");
Each execution produces a random sequence of ribbits and croaks.
$ ./whenever frog.we
Ribbit!
Croak!
Ribbit!
Croak!
Croak!
Croak!
Ribbit!
Even though statements are executed in a random sequence it is possible to write deterministic programs. Fredrik Hallenberg’s interpreter (the one I used for these examples) comes with a Whenever program that outputs the first 51 Fibonacci numbers in ascending order - eventually!