This essay serves as an explanation to what the language ><> is and what makes it so cool. I give an overview of in what ways it is esoteric and then walk through a sample program just to cement how interesting it is. I hope you like it as much as I do.
An esoteric language
The programming language ><> (spoken as “fish”) is what is known as an esoteric language. In one sentence, esoteric languages are impractical, but cool programming languages. You may have heard of some famous ones such as Brainfuck or Malbolge.
What sets ><> apart
><> is part of a family of languages known as Fungeoids which stems from the fact that they are similar to a language known as Befunge. These languages deviate from modern programming standards in many ways, but particularly the way that they evaluate code. At first, a ><> program might seem odd, but not too out of the ordinary. The following prints “Hello World!”
!v"Hello, World!"r! o>l?!;
But what’s actually going on is much more interesting than the code might seem to imply. You see, ><> is a two-dimensional, toroidal language, which means the way it evaluates the code is much different from what we’d expect.
Understanding how ><> works
OK, so what does that mean? Here’s the first key point of understanding how ><> code is interpreted: Every character is an instruction. The important implication of this is that code is parsed one character at a time and commands are executed depending on what character was parsed. Most people who program in ><> envision the interpreter as an instruction pointer (known in brief as an IP and also thought of as a fish) moving from character to character, executing commands at each. It starts at the beginning of the first line, parsing characters as it moves left-to-right.
A two-dimensional, toroidal language
><> reads one character at a time. “So what?” you might think. As it turns out, many esoteric languages do that. Where it’s first noticeable that ><> is different is the end of a line. For most of us, when we see the end of a line, we know intuitively that – barring certain circumstances – the next line to be evaluated will be the one beneath. But remember the first key point: ><> does not evaluate lines, but characters. Moreover, the instruction pointer cares not about the end of the line: it wraps around to the beginning after parsing the last character. This is what toroidal means. You can imagine the IP or fish as being on a torus; if it moves in a straight line it will eventually end up back where it started. This is the second key point to understanding ><>.
Bearing this in mind, you might think that ><> programs must therefore be one line. “What’s the deal with the Hello World example, then?” you’d ask. Indeed, this question brings us to the last element that makes ><> and its Fungeoid brethren unique: two-dimensionality. ><> programs aren’t one-dimensional, as we’ve established, so the IP doesn’t just parse left-to-right, it can parse top-to-bottom and the reverse of both as well! Certain instructions change the direction it moves: in the Hello World example,
v redirects the pointer to move top-to-bottom.
Last, but not least, the stack
Before we can get to understanding the Hello World program, there is one more salient fact about ><> to discuss, and that it is the fact that it is stack-based. If you’re not familiar with the stack data structure, you can imagine it as a literal stack of items. Much like how you can’t pull a plate from the bottom of a stack without toppling the rest, with the stack data structure you can’t easily modify or look at an arbitrary item – you only have the top to work with. ><> has one stack that most commands rely on. The arguments for computations are popped from the stack, and their results are pushed onto it.
Hello, World!, Explained
Now we have the requisite understanding to get an idea of what’s going on in the Hello World program I gave as an example. First, let’s work out the path that the IP traces. We can figure this out with knowledge of a few commands.
!skips the next instruction.
>point the IP in the direction you’d imagine (top-to-bottom and left-to-right, respectively).
?pops one element from the stack and evaluates it as if it were boolean (true or false). If it is falsey, it skips the next instruction.
;halts the program.
Try and guess what characters the IP will see in the Hello World program, reproduced below.
!v"Hello, World!"r! o>l?!;
Here is what it sees, in order, where the ellipsis and spaces around it means that some characters have been omitted.
!"Hello, World!"r!v>l?!o>l?!o> ... l?;
Let’s investigate what’s happening at each step.
- The instruction pointer first sees a
!, so it skips the next character,
- Then it sees a
". This character toggles string parsing mode. When the IP is in that mode, it pushes the ASCII code of each character it sees onto the stack instead of trying to evaluate the command that character represents. It keeps doing this until it reads another
"character. So “Hello, World!” (without quotation marks) is pushed onto the stack.
- Now I have a question for you: what is on the top of the stack? If you answered “!”, you’d be right. What does that mean for us? Well, suppose we were to have immediately after the code
"Hello, World!"a bunch of
os, which pops the top of the stack and prints the character associated with its ASCII code. What would happen is that “!dlroW, olleH” would be printed! Fortunately, we can prevent that by calling
r, which reverses the stack.
Let’s look at what happens after.
!v>l?!o>l?!o> ... l?;
- When the IP reaches the end of the line, it hits a
!, which skips the next instruction. Since it wraps around to the beginning of the line, that
!skips the first
!. This means that the IP can now reach the
vand be directed downward.
- It immediately sees a
>, returning it to parsing left-to-right.
- The next character it sees is
l, which pushes the length of the stack onto the stack. Right now there are 12 characters on the stack, so 12 is pushed onto it.
- It then sees a
?, which checks to see if the top of the stack is truthy. Only the value 0 is falsey, and because 12 is not 0, the next instruction is executed.
- This instruction is a
!, which skips the
;which would halt execution.
- It wraps around and then sees a
o, so it prints out the top of the (now reversed) stack.
- It then sees a
>which changes its direciton … to the direction it’s already pointing, effectively doing nothing. It continues to “loop” around, printing out the top of the stack until the stack is empty. Now that
;is reached, halting.
The output is the reversed contents of the stack: “Hello, World!”
That might’ve seemed like a lot to explain just one program, but I tried my best to be as thorough as possible. With this new understanding and (hopefully) appreciation for ><>, you’re now ready to go and write programs yourself! There is a pretty nice online interpreter and there are other interpreters listed here. If you’re interested in learning more about the language, I recommend you check out Sp3000’s great guide to ><> in code snippets as well as the ><> wiki page (which I now deem you ready to read through, if you’ve made it this far).
I’m including a lot of hyperlinks to the esoteric languages where they appear in this article, but it will likely confuse you further to read them if esoteric languages are foreign to you or if the idea of naming a programming language after an emoticon disturbs or puzzles you. Do check them out after reading, though! Go back.
Having a stack makes sense for a language like ><>, since what would be seem logically ordered to most of us would be impossible to parse in ><>. Take
3+5for example. Now we return to our first key point. The IP sees a
3and, as it turns out, pushes it onto the stack. It then sees a
+, but at this moment in time it knows nothing about the character in front of it. So if we gave ><> the program
3+5it would unsurprisingly error when it reaches the
+and many other operators expect at least two values on the stack – without another value
+has nothing to add! You can see how without a singular stack, ><> would have difficulty giving arguments to its operators.
3+5, by the way, would be represented as
35+;in ><> (the
;is important, but not a part of the addition process), and its result would be pushed onto the stack. Go back.