Friday Pathological Programming Language: Whenever

Jul 28 2006 Published by under pathological programming

I was hoping for a bit of a vanity post for todays pathological programming language in honor of my 40th birthday (tomorrow), but I didn't have time to finish implementing my own little piece of insanity. So it'll have to wait for some other occasion.
Todays pathological programming language is a really simple monstrosity called ["Whenever"][whenever]. Whenever is a programming language where programs get executed in *random* order, and there are *no* variables. The only state, the only way of manipulating information in a Whenever program is by manipulating the collection of executable statements itself: the program is both the code *and* the data at the same time.
The basic program model of Wheneveris: you write a set of statements. The statements are inserted into a grab-bag by the interpreter. The interpreter then repeatedly picks a statement out of the bag *at random* and executes it. It keeps doing that until there are no more statements in the bag.
Everything in Whenever is done by manipulating the statement bag.
Each statement is labeled by a number. The number has no direct meaning; it's just an identifier that will be used to reference the statement. The numbers assigned to lines don't have to match the order in which the lines were written in the source file; and they have no effect on the order by which statements are pulled out of the bag.
So how do you do anything in this crazy language?
There's a print statement for printing things out. So, for example,
23 print("Hello worldn");
is the hello world program. Since there's only one statement, it'll get grabbed from the statement bag, and executed.
There's also a read statement, which reads a number from standard input, and then acts as if the statement were the number that it read.
The simplest statement is just a number. A number statement *adds* a copy of the line identifier by that number to the bag. If the number is negative, then it *removes* a copy of the statement from the bag. So, for example:
23 print("Hello worldn");
11 23;
would print "Hello world" twice. If 23 were executed first, it would print "Hello world", and then only 11 would be in the bag, so it would execute 11, which would add 23 to the bag. If 11 went first, then it would add 23 to the bag, and there would be two 23s in the bag, which would get executed.
You can add multiple copies of a line to the bag: 5#3 adds 3 copies of statement 5 to the bag. And you can add multiple statements to the bag at once, by separating them with a comma. So:
17 21, -2, 3#4, -5#2;
Would insert one copy of statement 21 and four copies of statement 3 to the bag; and remove one copy of statement 2, and two copies of statement 5.
You can also do any normal arithmetic operation on numbers. The result of the arithmetic operation is interpreter as a line number.
There's also two kinds of conditionals, "defer" and "again". Defer takes a parameter which is evaluated to a line number, and if there are any copies of that line number in the bag, then it reinserts itself, and doesn't do anything else. If there are no copies of the parameter in the bag, then the statement on the rest of the line is executed.
Again, an example:
1 print("Hello");
2 defer(1) print("Worldn");
is a more complicated version of hello world.
The "again" statement is very similar to the "defer" statement; but if its argument is true (i.e., evaluates to a statement that is present in the bag), then it adds a copy of itself to the bag; whether the parameter is true or false, it then executes the rest of the statement.
There's one helpful built-in function: N(x) returns the number of copies of statement x in the bag.
So, a couple of interesting example programs:
1 defer (4 || N(1)<N(2) && N(2)<N(3)) print(N(1)+" bottles of beer on the wall, "+N(1)+" bottles of beer,");
2 defer (4 || N(1)==N(2)) print("Take one down and pass it around,");
3 defer (4 || N(2)==N(3)) print(N(1)+" bottles of beer on the wall.");
4 1#98,2#98,3#98;
This first ensures that statement four runs first: statements 1, 2, and 3 will all defer until 4 has been executed. Once four is run, there are 99 copies of statements 1, 2, and 3 in the bag. The rest of the defer statement makes sure that 1 executes before 2, and 2 before 3; so it cycles through 1, 2, 3 99 times. Pretty simple, right?
How about this?
1 again (1) defer (3 || N(1)99) 2#N(1),3,7;
2 again (2) defer (3 || N(2)99) 1#N(2),3,7;
3 defer (5) print(N(1)+N(2));
4 defer (5) print("1");
5 4,-3,7;
6 defer (4) 3;
7 7;
8 defer (N(7)<100) -1#N(1),-2#N(2),-7#100;
9 defer (3 || 6) 1,3;
If you look carefully.. It generates the first 100 fibonacci numbers.
It's an incredibly simple language. Simple, but quite twisted, and seriously mind-warping to try to program: you need to always keep track of the fact that the statements that represent your data could get selected for execution, which will modify the data unless you used a "defer" as a guard, but then you need to make sure that the guard gets preserved correctly... It's quite devious.
[whenever]: http://www.dangermouse.net/esoteric/whenever.html

No responses yet

  • Since it's your birthday tomorrow you should tell us some amusing anecdotes from your work as a computer scientist.

  • Ithika says:

    I think the only appropriate thing to say here is: clucking bell. That's not a programming language, it's a form of torture by logic!

  • Are there practical applications for this language, or was it created by a bunch of programmers during a drunken stupor?
    * I would hate to try to do a code review of this language, or try to debug it.

  • Blake Stacey says:

    No One of Consequence wrote as follows:

    Are there practical applications for this language, or was it created by a bunch of programmers during a drunken stupor?

    I'm not so sure ethanol was the compound involved. . . .

  • Mark C. Chu-Carroll says:

    Ithika:

    I think the only appropriate thing to say here is: clucking bell. That's not a programming language, it's a form of torture by logic!

    Exactly! Beautiful, isn't it?

  • Mark C. Chu-Carroll says:

    Blake, NOoC:
    Having been involved in the design (is "designing" the correct word? perhaps spawning? excreting?) of several warped programming languages, I feel obligated to inform you that *no* intoxicating/mind-altering substances are necessary. The mind of a programming language geek is already so deeply warped that this sort of thing can be produced without any chemical assistance.

  • Mark C. Chu-Carroll says:

    NOoC:

    Are there practical applications for this language, or was it created by a bunch of programmers during a drunken stupor?

    If there were practical applications, it wouldn't be a pathological programming language :-).
    Seriously, among PL geeks, designing bizzare languages like this is a hobby. The point isn't to create something *useful*, but to create something that is deeply bizzare, and yet somehow compelling.
    I would be absolutely *shocked* to find out that there was *any* useful algorithm that would be more natural to code in Whenever than in a more normal programming language. But you've got to admit that there's something really fascinating about the idea of the program *being* the data in this extreme way.

  • Brian Postow says:

    I assume that this (and all of the pathalogical languages you're going to describe) is Turing Complete?
    Also, when are you going to get to Intercal?

  • Mark C. Chu-Carroll says:

    Brian:
    Yes, Whenever is turing complete. If I show a language that is less that TC, I'll be sure to mention it.
    I'm not planning to do intercal: I *hate* intercal. It carries the joke so far that it just loses its humor. It mushes so many different silly things together (ignore, come from, please, the pointlessly strange arithmetic ops, etc.) that it's just too much. It's like the C++ of pathological programming languages.

  • Mark C. Chu-Carroll says:

    Thomas:
    Alas, I'm really not allowed to talk about work here on the blog. Part of my employee agreement includes confidentiality stuff; I'm never allowed to write about what I do at work without first getting permission. If I strip out enough details to work around that, then any stories I could tell would become so vague that they wouldn't be amusing anymore.

  • andrea says:

    Ow, brain hurty!
    Now my frontal lobes feel all stretched out of shape, like socks worn two days in a row. Some mental subprocessor froze up partway through though, but that's likely because I'm not a programmer (last time I had a class in such we were still using punch cards...) Really, the thing's interesting, in a twisted kinda way.

  • Torbjörn Larsson says:

    Pathological programming (spaghetti code, for example) and pathological languages takes brain teasers to new places.
    When I saw the first part of the description of Whenever, my immediate reaction was that the corresponding language Whatever could never work. (Something like randomised instructions lines, perhaps.) But the use of "defer" makes me wonder.
    I bet Whenever Whatever is a bitch though.

  • Torbjörn Larsson says:

    PS. I got curious about a language using PLEASE so I googled Intercal. (And they say PLEASE GIVE UP to exit, nice!) They refer to a community of technomasochists ( http://www.catb.org/esr/intercal/ ).
    Thingifying social relations (feticshisms) is as interesting to me as humanifying technical areas (anthropomorphising). Ie not at all. The world is a huge playground anyway. Good thing they are joking. I think. DS

  • Xanthir says:

    The beautiful thing about pathological programming languages is taking a single strange idea and basing an entire language around it. Whenever is certainly beautiful in this way. Befunge was as well. Brainfuck was beatiful in a slightly different way (as MarkCC said, it's like programming a stack-based Turing machine).
    Intercal's central idea, however, is to be as ugly as possible. While they officially meet my definition of 'beautiful', it can never be described by that word.

  • Blake Stacey says:

    I can't wait to see the DeCSS implementation in Whenever.
    . . . Courtney?

  • Sergio Giraldo says:

    Nice serie, Mark. 2 comments about your examples (following will make sense only if I understood correctly; if I didn't, excuse me, whenever is devious :
    In the beer example the defer in statement 1 should be :
    1 defer (4 || N(1)

  • Sergio Giraldo says:

    Nice serie, Mark. 2 comments about your examples (following will make sense only if I understood correctly; if I didn't, excuse me, whenever is devious :
    In the beer example the defer in statement 1 should be :
    1 defer (4 || N(1)

  • Sergio Giraldo says:

    Two tries to post and MT didn't recognize the less than sign. Below, lt means it. Sorry for unintended flood.
    Nice serie, Mark. 2 comments about your examples (following will make sense only if I understood correctly; if I didn't, excuse me, whenever is devious :
    In the beer example the defer in statement 1 should be :
    1 defer (4 || N(1) lt N(2) && N(2)=N(3))
    With N(2) lt N(3)the random order can be :
    4 (N(1)=N(2)=N(3)=99)
    1 (N(1)=98 N(2)=N(3)=99)
    2 (N(1)=98 N(2)=98 N(3)=99)
    1 again (N(1)=, N(2)=98 ,N(3)=99)
    when it should be 3
    In Fib example defer in statement 3 should be
    3 defer (5 && N(4)=0) print(N(1)+N(2));
    If you don't test N(4) you can pick the following order :
    5
    4 (Print 1)
    6 (Put statement 3 back in bag - you removed with statement 5)
    3 (Print 2 : N(1) = 1, N(2) = 1 and statement 5 was already executed so it will execute its action)
    At this point you have printed 1 2 instead of 1 1

  • Xanthir says:

    Sergio - Looks like you're right. If 4 has already executed, then the defer properties of line 1 is:
    N(1)

  • Over the weekend, I realized that although Whenever is not a good model for human rational thought*, it has interesting similarities to the lowest level of biology, where genes are read as units, but the set of all active genes isn't read in any particular order. 'defer' and 'again' don't really correspond to promoters or suppressors, so it's more of a thematic similarity, but still, interesting.**
    *Non-Euclidean shoggoth thought, now...
    **More interesting than trying to use my psychic powers to make the traffic light change, anyway.

Leave a Reply