20 Intriguing, Unusual, and Goofy Programming Languages
A collection of esoteric and thought-provoking programming languages.
[ history ]Originally posted on Dev.To
"Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!"
Despite how it can feel sometimes, programming languages are usually designed to make our lives easier. Expressing complex relationships between classes, bounds-checking data, and interacting with the user is much easier in Java than it is in CPU opcodes, for instance (and only slightly less verbose).
But some language designers have other goals in mind. A programming language might be designed for easy vectorisation of data, or easy multithreading, or performance. And some are designed so that the only keyword is chicken
. Different strokes.
Below is my curated list of 20 interesting, beautiful, and disorienting programming languages. Most of these are considered "esoteric" though some of them are actually used by serious programmers on a regular basis. See if you can tell which are which.
Table of Contents
- brainfuck
- chicken
- legit
- Malbolge
- APL
- (D♭, D♭♭, and) Velato
- Piet
- Whitespace
- INTERCAL
- Unary Except Every Zero Is Replaced with the Title of This Programming Language or, Alternately, Is Replaced with the Smallest Counter-Example to the Goldbach Conjecture. Compilers and Interpreters Only Have to Implement the Former Option
- Seed (and Befunge)
- LISP
- Funciton
- ///
- Factory
- golfing languages
- languages with 2-dimensional source code
- languages which emphasise source code aesthetics
- languages built so that the source code looks like ___
- Q#
#1. brainfuck
Related: Unibrain
Brainfuck (sometimes styled brainf___, brainf***, or just BF) is the poster child for esoteric programming languages (esolangs). A program which prints "hello world" in BF looks like:
+[-[<<[+[--->]-[<<<]]]>>>-]>-.---.>..>.<<<<-.<+.>>>>>.>.<<.<-.
Brainfuck is a tape-based language. You can imagine a program in a tape-based language as an extremely long, one-dimensional array of (initially) zeros. There is a pointer, which is initially at one end of the tape and can be moved forward or backward, one memory cell at a time. The values in cells can be incremented or decremented (restricting them to integer values), and there are brackets which allow for loops.
There are eight commands in the BF language specification. The cell to which the pointer is currently pointing is referred to as the "current cell":
> move the pointer one cell to the right
< move the pointer one cell to the left
+ increment the value in the current cell
- decrement the value in the current cell
. output the character represented by the value in this cell
, input a character and store it in the cell at the pointer
[ jump past the next ] if the cell under the pointer is zero
] jump back to the most recent [ if the cell under the pointer is nonzero
That's it! Any other character which appears in a brainfuck program is assumed to be a comment and is ignored. Brainfuck is Turing complete and so, theoretically, it can perform any computational task that any other programming language can, though it might take a bit more time to program it in BF.
Brainfuck has inspired countless imitator languages, including:
- ( ͡° ͜ʖ ͡°)fuck -- similar to brainfuck, but the commands are all replaced by Lenny faces
- Bodyfuck -- a gestural interpreter for brainfuck
- I hate your bf-derivative really I do -- a language with the same character set as BF, but where all of the characters have different meanings; designed to frustrate BF enthusiasts
- JSFuck -- an "esoteric subset" of JavaScript, which only uses the characters
+
,!
,(
,)
,[
,]
, creating a BF-like syntax in which a "Hello, World!" program requires more than 10,000 source code characters - TreeHugger -- a derivative of BF which uses an infinite binary tree data structure, rather than an infinite tape
- POGAACK -- a BF / Chicken crossover
#2. chicken
Chicken is probably the best known single-keyword language, even though, technically, there are eleven instructions in the stack-based Chicken language, which correspond to eleven opcodes, numbered 0 through 10.
Chicken was inspired by a paper written by Doug Zongker to poke fun at unintelligible academic presentations.
The opcode number gives the number of times (given by #
in the below table) that the chicken
keyword must appear (separated by spaces) in order to represent that specific instruction:
# | command |
---|---|
0 | stop execution |
1 | push the string "chicken" onto the stack |
2 | add the top two values from the stack |
3 | subtract the top two values from the stack |
4 | multiply the top two values from the stack |
5 | compare the top two values from the stack for equality, push a "truthy" or "falsy" result onto the stack |
6 | double wide instruction. Next instruction indicates source to load from. 0 loads from stack, 1 loads from user input. Top of stack points to address/index to load onto stack. |
7 | top of stack points to address/index to store to. The value below that will be popped and stored. |
8 | the top of stack is a relative offset to jump to. The value below that is the condition. Jump only happens if condition is truthy. |
9 | interprets the top value on the stack as ASCII and pushes the corresponding character |
10+n | pushes the literal number n-10 onto the stack. |
When the program stops, whatever happens to be on the stack is printed to the screen (this is common in languages designed for code golfing). This means that a self-replicating quine program is quite easy to create in the language:
chicken
As the keyword chicken
appears once in the first line, the string "chicken" is pushed onto the stack. The end of the program is then reached and the stack (which contains only the word "chicken") is printed to the screen. The program has reproduced its own source code exactly. This is quite difficult to do in most languages, though Mame (given name Yusuke Endoh) has created this absolutely bonkers quine relay, which cycles through 100 different programming languages, each outputting the source code of the next one. (Seriously, go check out some of their projects on GitHub, they're nuts.)
#3. legit
Related: Dirst
Legit (pronounced with a hard "g") is a Turing-complete programming language where programs "are defined entirely by the graph of commits in a Git repository." The content of the repository itself is completely ignored.
Legit instructions are encoded in the commit messages in a Git repo. Execution proceeds normally from a commit to its parent (moving down the output of a git log --graph --oneline
command). If a commit has multiple parents, they form a stack of commands, indexed from 0 (the eldest commit), the top of the stack is popped and value must be a number corresponding to the proper parent index. Program flow can be controlled, though, with goto
-like commands that can jump to particular commits.
A "Hello World!" program in legit looks like:
$ git log --graph --oneline
* b63fd70 (HEAD -> master, origin/master, origin/HEAD) Merge pull request #1 from rohieb/master
|\
| * 1f44c51 0
| |\
| |/
|/|
* | b9e1e95 "Hello world\n"
| * fbb02fe "Hello world!\n"
|/
* 8013037 (tag: reverse-loop) dup
|\
| * 6883822 write 1 left [reverse-loop]
* e0a4d04 (tag: print-loop) 1 right read dup
|\
| * d646ef4 put [print-loop]
* 25a3a62 quit
Notice that there are two lines which say "Hello World", and the second one has a "!" added at the end. The creator of the language made this program, then merged a PR for that change. Since legit programs are themselves Git repositories, there's no such thing as version control with a legit program, at least version control with Git itself. This means programs can end up looking messy as changes are made.
The language creator, Sebastian Morr, has discussed how difficult it can be to write legit programs:
"I’ll be honest with you: I got tired of writing Git commands by hand to create legit programs. One consequence of the execution going top-down is that you have to write your programs backwards, and each time I’d make a typo, I’d have to start all over, because the commits above that would be invalidated. So… I started to write shell scripts, which would then generate my legit programs."
In spite of this, he's managed to write a brainfuck interpreter in legit, indirectly showing that legit is Turing complete. Morr's challenge to users of his language? Write a legit quine:
"Write a legit program that prints the Git commands required to create itself! Good luck."
#4. Malbolge
Named after the eighth circle of Hell from Dante's Inferno, Malbolge is a language specifically designed to be nearly impossible to use. Malbolge programs use base-3 arithmetic (so there are tritwise operations instead of bitwise ones), alter and encrypt their own source code, and are actively sabotaged by bug-features in the implementation and specification.
The creator of Malbolge, Ben Olmstead, says that if he could make the language more difficult to code in, he would:
"I know there is a mismatch between the documented and implemented tables. I have noticed that some people decide that the bug is in the specification, and others decide the bug is in the implementation; it certainly makes Malbolge harder to use, and fragments the user community (such as it is)."
"If I were to make a Malbolge 2000, I would definitely make the documentation subtly wrong."
Malbolge is so difficult to write in, that even Olmstead has never written a program in it, beyond "a program that printed 'H' and exited". The first "Hello, World!" for Malbolge wasn't written, it was discovered eight years after the language was released by a beam search algorithm, exploring the space of all possible Malbolge programs until one was found to produce the correct output.
Here's a sample "Hello World!" program in Malbolge:
(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc
Ryan Kusnery, collector of weird languages, has declared that "the day that someone writes, in Malbolge, a program that simply copies its input to its output, is the day my hair spontaneously turns green. It's the day that elephants are purple and camels fly, and a cow can fit through a needle's eye."
Despite Kusnery's certainty about the impossibility of such a program, professional esoteric programmer Matthias Lutter has managed to write a Malbolge quine, which, though coming in at 800+ lines, does manage to exactly output its source code (try it out here if you've got about an hour to waste).
#5. APL
I think A Programming Language (APL) is one of the most impressive esoteric languages (if you can call it that) I've ever encountered, mainly because it existed decades before most other languages on this list.
The only other major languages around at the time of APL were COBOL, LISP, FORTRAN, and ALGOL, the spiritual precursor to the C family of languages.
APL was created by Kenneth Iverson in the early 1960s with a primary goal of providing easy, concise manipulation of arrays, matrices, and higher-dimensional data structures. Matrix manipulation is common in mathematics, physics, and computation-heavy sciences. Providing an easy way to create and manipulate these data structures should make these scientists' lives easier. Theoretically.
Manipulation of multi-dimensional arrays is of course still critical to these fields, so modern languages like MATLAB, Wolfram Language, and R have drawn much inspiration from APL. The biggest difference between these more modern languages and APL is APL's character set.
In an ALGOL-like (C-like) language, you might define an array of numbers like:
int array[] = { 1, 2, 3, 4, 5, 6 };
In APL, this looks like
array ← ⍳6
The leftwards-pointing arrow ←
is used for assignment, and the iota character ⍳
is used to create an array of integers from 1
to N
, where N
is the number which follows the ⍳
character.
APL introduces a wide variety of uncommon characters which perform different functions. This has the effect of keeping the code itself very compact, often at the cost of readability (for the programmer accustomed to languages like ALGOL, FORTRAN, COBOL, or LISP). The following C code:
int arr[] = { 4, 5, 6, 7 };
int len = sizeof(arr)/sizeof(arr[0]);
int sum = 0;
for (int ii = 0; ii < len; ++ii)
sum += arr[ii];
...can be compressed dramatically with APL:
sum ← +/(3+⍳4)
APL uses vectorised operations to add 3
to every element of the array created by ⍳4
. ⍳4
creates the array [1, 2, 3, 4]
, and 3+⍳4
adds 3
to each element of that array, to get [4, 5, 6, 7]
. Then, the "sum over" operator +/
sums the elements of that array 4 + 5 + 6 + 7
to get 22
, which is then assigned to sum
via the leftward-pointing arrow.
I hope this explanation has given you just a small taste of what APL is capable of. Some modern languages like R make heavy use of vectorised operations, which can make manipulation of data very easy and concise, but it does take some getting used to.
Masters of APL can write incredibly complex programs using only a few dozen characters (though many of these are APL-specific characters). For your enjoyment / confusion, here is the entirety of John Conway's Game of Life, written in Dyalog APL, a modern dialect of the language:
life ← {↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
If anyone can explain that to me in the comments, step-by-step, I would be extremely impressed.
#6. (D♭, D♭♭, and) Velato
Related: Choon, Musical Notes
D♭ (pronounced "dee flat", like the musical note) and D♭♭ ("dee double flat") are joke languages, never actually implemented as far as I can tell. Which is unfortunate, because D♭ was supposed to offer "minor but key improvement[s]" to the C# language, including:
-
LowerClass
,MiddleClass
andUpperClass
objects, which are distinguished according to the properties they can have and their permitted interactions with the otherClass
es.UpperClass
entities can becomefriends
via theLobby
, for instance:UpperClass BigShotRepublican { Investments portfolio; Yacht coasts[6]; Lobby<Politicians> inPocket; }
-
More "visually intuitive" exception handling, with the addition of new keywords
throwUp
,upChuck
,puke
,ralph
, andhurl
. As the language documentation notes:These convey different levels of exception severity and can be used by your application to determine the size of the
bucket
needed to catch the exception... Sometimes thebucket
can overflow, so you'll need to stackbucket
s so they catch the overflow. -
New generics, including
Hash
,Pot
,Coke
, andCrystal
. According to the documentation, "[a]ll the generics are handled in theStreetCorner.Pharmacy
namespace" and can "accelerate the performance of your application" and "enhance your end-user experience", but should be used in moderation.
While D♭ would have offered these (and more) improvements on the C# language, D♭♭ would have provided similar benefits (presumably) over the C language.
Velato is another musical language, though it differs from D♭ and D♭♭ in that it's actually been implemented. Velato source code is written in MIDI files -- the pitch and ordering of notes determines the action of the program.
The first note of the program is the "root note", which can be changed by playing the note a major second interval from the root note. Other intervals and grouping of notes determine other operations; for example, the modulus operator %
is encoded by playing the fifth, then the fifth again, then the sixth of the root note.
A sample "Hello, World!" program in Velato might look like:
Though the ordering of concurrent ("stacked") notes does affect the operation of the program, so sheet music alone can't fully describe a Velato program.
#7. Piet
Related: Skastic
Another artistic esoteric language is Piet, named after the Dutch painter Piet Mondrian, famous for his abstract art, composed of simple geometric shapes:
Piet programs are "written" as pixels in bitmap files, in 3 different shades of 6 different hues, plus white and black, for a total of 20 different colors. The "colorful" colors (all but white and black) are arranged in a torus, where moving from the base hue to its "dark" hue to its "light" hue and back to the base hue is all considered movement in the same (positive) direction. Similarly, movement from red -> yellow -> green -> cyan -> blue -> magenta -> red -> ... is cyclical and directed (positive), as well.
When the program starts, Piet "reads" the colors of the pixels in the bitmap, starting in the top-left corner of the image. Execution proceeds from the left to the right until a "wall" of black pixels is encountered, at which point, the direction of program execution changes and pixels are read from top-to bottom (always changing direction by rotating by 90 degrees clockwise). The edges of the canvas are considered "black pixels", as well.
The transitions between colored areas encode the action of the program. For instance, if we "rotate" the hue by one unit (e.g. from red -> yellow) as we move along the image, that encodes an "add" action. If we also change the "lightness" by one unit (e.g. from red -> dark yellow), that encodes a "subtract" action. Movement into or out of a white area encodes no action, and is the only way to change the color without performing an action (this is useful for loops).
Because the program only depends on transitions between colors, and not the colors themselves, or the direction of movement across the "canvas", programs can be very simple or very "artistic". For example, here's a program which gets a number from the user, squares it, then prints the square:
...and here's that same program, zhuzhed up a bit:
One of the nicest Piet programs I've seen is this one, which prints "Piet":
Now we just need someone to combine Piet and Velato and create a language where programs are encoded within multimedia files.
#8. Whitespace
Related: Anguish
The importance of whitespace characters (spaces, line breaks, tabs, etc.) in a programming language exists on a spectrum. Some languages don't care very much, some care quite a lot (see: Python), and at least one language only cares about whitespace characters. That language is called -- creatively enough -- Whitespace.
All visible characters (digits, letters, punctuation, etc.) are ignored by Whitespace. In fact, most whitespace characters are actually ignored by Whitespace, too. The space (ASCII 32), tab (ASCII 9) and line feed (ASCII 10) characters are the only characters which carry any meaning in a Whitespace program.
A "Hello, world!" program in Whitespace looks like this ("dots" .
added to the end of each line so "trailing whitespace" is not removed in this browser):
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
(You can click and drag to highlight the spaces and tabs in the code above. Or try it out in this web REPL.)
Whitespace code is written one command at a time, where a particular sequence of tabs, spaces, and line feeds indicates a certain category of commands -- I/O, stack manipulation, arithmetic. Once the category is selected, the particular command in that category is selected with another sequence of tabs, spaces, and line feeds. All numbers are binary encoded (space = 0, tab = 1) and all characters are indicated by their ASCII indices (again, binary encoded, so tab-space-space-space-space-tab-tab is 1000011
or 67
or C
).
All sorts of programs have been written in Whitespace, including quines, Brainfuck interpreters, and more. And some Whitespace programs have surely been hidden in the source code for other languages. These polyglot programs could be run as Whitespace code -- where all the visible characters are ignored -- or as code in the "host" language, provided the whitespace needed for the hidden Whitespace program is not significant.
Just in case you needed another thing to worry about.
#9. INTERCAL
INTERCAL, short for Compiler Language With No Pronounceable Acronym, is arguably the first-ever esoteric language.
"...created as a parody by Don Woods and James M. Lyon, two Princeton University students, in 1972...[INTERCAL] satirizes aspects of the various programming languages at the time, as well as the proliferation of proposed language constructs and notations in the 1960s." [ source ]
INTERCAL is designed to be confusing and difficult to work with. Common symbols are pointlessly renamed ('
is a "spark", "
is "rabbit ears", :
is a "twospot", ...), numbers can only be given as input by spelling out the digits one at a time (TWO FIVE SIX
is the number 256
), and an undocumented "feature" means that programs can be rejected by the compiler for not being polite (not using the keyword PLEASE
enough) -- or for being overly polite (using PLEASE
too much).
Wikipedia offers this amazing quote from the INTERCAL reference manual
It is a well-known and oft-demonstrated fact that a person whose work is incomprehensible is held in high esteem. For example, if one were to state that the simplest way to store a value of 65536 in a 32-bit INTERCAL variable is:
DO :1 <- #0¢#256
any sensible programmer would say that that was absurd. Since this is indeed the simplest method, the programmer would be made to look foolish in front of his boss, who would of course happen to turn up, as bosses are wont to do. The effect would be no less devastating for the programmer having been correct.
INTERCAL is a very forgiving language, though. Anything the INTERCAL compiler -- ick
-- can't understand is simply ignored. This means that all INTERCAL programs are by definition bug-free! Which is good, because the original INTERCAL was written for the EBCDIC character set, but latter versions moved to ASCII. As a result, different dialects of INTERCAL have totally different instruction sets.
And for the fifteen people on the planet who want to get INTERCAL working with .NET, you're in luck -- someone's had enough free time to make that a reality.
#10. Unary Except Every Zero Is Replaced with the Title of This Programming Language or, Alternately, Is Replaced with the Smallest Counter-Example to the Goldbach Conjecture. Compilers and Interpreters Only Have to Implement the Former Option
In the section on brainfuck, above, we saw just a tiny sample of the hundreds of BF-derivative languages that exist. While there are some interesting derivative languages, I tried my best not to include any of them, since this article would quickly devolve into nonsense.
However, there's one special bit of nonsense that I'd like to share with you from the brainfuck world. It's a little language called Unary Except Every Zero Is Replaced with the Title of This Programming Language or, Alternately, Is Replaced with the Smallest Counter-Example to the Goldbach Conjecture. Compilers and Interpreters Only Have to Implement the Former Option. (For the rest of this entry, I will refer to the aforementioned language as "this language".)
This language is what it sounds like, it's a derivative of the Unary programming language. Unary has the same commands as BF, but they're encoded in a unary numeral system -- that is, a system which only has a single symbol. In this case, that symbol is 0
.
Unary systems aren't as unusual as they may sound, and you've almost certainly encountered one before. If you've ever had to track a hand-raised vote or keep track of wins and losses in a series of games, you may have used tallies. In this system, a single straight line represents
1
, two single straight lines represent2
, and so on. Tally marks are a unary numeral system.
In Unary, brainfuck commands are encoded in binary using the following table:
brainfuck command | binary index |
---|---|
> | 000 |
< | 001 |
+ | 010 |
- | 011 |
. | 100 |
, | 101 |
[ | 110 |
] | 111 |
To write a Unary program, one starts by writing a brainfuck program. As an example, here's a very simple BF program that simply adds the number 2
to the number 3
and prints the result to the terminal:
++>+++[<+>-]++++++++[<++++++>-]<.
In Unary, we first convert all of these BF symbols to their binary equivalents:
010010000010010010110001010000011111010010010010010010010010110001010010010010010010000011111001100
...then, we prepend a 1
to this very large binary number:
1010010000010010010110001010000011111010010010010010010010010110001010010010010010010000011111001100
...and finally, we convert this number to unary. Wolfram|Alpha tells me that this number is equivalent to
812,443,533,011,490,965,255,226,984,396
...in decimal ("about 812 octillion"), so a unary representation of this number would simply be that many 0
s, back-to-back.
What makes this language different from the Unary language is that this language then replaces each of those 0
characters with either:
- the title of this programming language, or, alternatively
- the smallest counter-example to the Goldbach Conjecture
The Goldbach Conjecture (aka. "Goldbach's Conjecture") states that
...every even integer greater than 2 can be expressed as the sum of two primes. [ source ]
Presumably, we would replace each 0
with that smallest integer, which (as of this writing), is bounded on the low end by at least 4 * 10^18. However, since Goldbach's Conjecture hasn't yet actually been disproven, we can't replace 0
with anything except the name of this programming language. Luckily, "compilers and interpreters only have to implement the former option".
Even so, the above 2+3
program in this language would be quite long, as the name of this programming language is 238 characters. Encoding that single small program in this language would require about a billion trillion terabytes of disk space. This language is a strong contender for the most resource-inefficient language in the universe.
#11. Seed (and Befunge)
Seed is related to an earlier esolang named Befunge, in which programs are written on a 2-dimensional grid. In Befunge, the user defines "arrow" instructions to move pointers around the program. For example, a Befunge "Hello, World!" could be written like:
> v
v ,,,,,"Hello"<
>48*, v
v,,,,,,"World!"<
>25*,@
You can see the >
v
, and <
characters, which literally point in the direction that the code should be interpreted / compiled. (There's also a ^
character which is not used here.)
Befunge was designed specifically to be difficult to compile. Because it can be executed in any one of four directions (left-to-right, right-to-left, top-to-bottom, or bottom-to-top), and because it provides facilities for self-modifying code, it can be extremely difficult for a compiler to reason about Befunge source code.
Seed takes this relatively nice (but definitely unusual) language and makes it completely ridiculous. A Seed program is only ever composed of two numbers: a length, and a random seed. The random seed is fed to a Mersenne Twister algorithm, which is used to generate a random string of the specified length. Seed will then attempt to run that random string as a Befunge program. That's it.
Seed is an extremely easy language to program in -- all it requires is two numbers -- but, because of its inherent randomness, it requires huge amounts of resources. Programming in Seed usually means generating lots of random programs of a specified length and checking the program output against the desired output. As there are 96 valid characters in a Befunge program (ASCII 32 through 126, plus line feed), there are 96^n
possible Befunge programs containing n
characters. Testing all valid programs of length 5 therefore requires generating and running over 8 billion unique Befunge programs.
In spite of this, some enthusiasts have somehow managed to write Seed programs which actually do useful (?) things. For example, this program:
1 186
...does nothing and exits, while this program:
4 80814037
...prints the character 'h'
. Because the number of possible programs increases exponentially as the length of the program increases, a "Hello World" program is incredibly difficult, yet esolang enthusiast Krzysztof Szewczyk has still managed to find a solution with a random seed of only 4151 digits. Like I said, easy to program in!
#12. LISP
The more I learn about LISP, the more I like it. First released in 1958, LISP is one of the oldest high-level languages still in common use today (only a year younger than FORTRAN, which is still popular in the scientific community). LISP stands for LISt Processor and essentially that's what it does -- it processes lists.
Everything in LISP is either an atom or a list. Lists can contain atoms, as well as other lists. Atoms are "indivisible" and are things like numbers, strings, and so on. For example, the following list:
(1 "hey" (+ 7 x))
...contains three elements: the atom 1
, the atom "hey"
, and the list (+ 7 x)
, which contains three elements of its own.
Note that there are no type declarations in LISP. The reason for this is twofold. First, LISP uses a kind of dynamic typing and can check whether an atom is a string or a number, and can provide compile-time warnings if a programmer tries to code some odd operation like dividing a number by a string. Second, LISP is such an old language that type theory hadn't really yet evolved as a field of study at the time the language was created. So "list" and "atom" are the only two types.
Here's a simple LISP program (in the "Common LISP" dialect) which asks a user for a radius, and then gives the area of a circle with that radius:
(defun AreaOfCircle()
(terpri)
(princ "Enter Radius: ")
(setq radius (read))
(setq area (* 3.1416 radius radius))
(princ "Area: ")
(write area)
)
(AreaOfCircle)
Notice how every statement in the above program is a list, including I/O and execution of various functions. LISP has the ability to manipulate lists, as well:
(append '(1 2 3) '() '(a) '(5 6))
Here,
'x
is syntactic sugar for(quote x...)
, which simply returns the elementsx...
without evaluating them (which is the default behaviour).
The above list manipulates several other lists by appending them to one another, in order. The result of the above code snippet is the list:
(1 2 3 a 5 6)
Note how the atom
a
hasn't been evaluated and replaced with a number or string.
Because LISP provides methods to operate on lists, and because every LISP program is itself composed of nothing more than lists, LISP programs define data structures within the LISP language! This means that macros -- code which manipulates and runs other bits of code -- are common among LISP developers. LISP syntax defines program input, output, and the source code of the program itself. This concept, called homoiconicity, is part of what makes LISP a bit foreign to users of ALGOL-like (C-like) languages.
If you want to learn a cool, new (to you, at least) language in 2020, may I suggest LISP?
#13. Funciton
Funciton is a programming language whose name looks like someone misspelled "function" and which I always pronounce as "funky town" in my head when I read it.
Funciton is a flowchart-like, two-dimensional language. A factorial function in Funciton might look like:
╓───╖
║ ! ║
╙─┬─╜ ┌───╖ ╔═══╗
┌─────┴─────┤ > ╟──╢ 2 ║
│ ╘═╤═╝ ╚═══╝
╔════╗ ┌───╖ │ │
║ −1 ╟──┤ + ╟─┴─┐ │
╚════╝ ╘═╤═╝ │ │
┌─┴─╖ │ ╔═══╗ │
│ ! ║ │ ║ 1 ║ │
╘═╤═╝ │ ╚═╤═╝ │
│ ┌─┴─╖ ┌─┴─╖ │
│ │ × ╟──┤ ? ╟──┘
│ ╘═╤═╝ ╘═╤═╝
└─────┘ │
Every element of a Funciton program is written inside of a rectangle (or "box") made of ASCII lines and double-lines. The lines between boxes carry data around the program. As Funciton programs are rotation-invariant, there are five possible kinds of boxes:
- double-lined on all sides: literal value OR input OR comment
- double-lined on three sides: lambda expression
- double-lined on two adjacent sides: function call
- double-lined on two opposite sides: function declaration
- double-lined on a single side: invoke a lambda function
- double-lined on no sides:
NOT
operator (see below)
If a box has no connectors, then no data can be passed to it or read from it, so that box becomes a comment:
╔═════════════════════════════════════╗
║ Won't you take me to... Funciton? ║
╚═════════════════════════════════════╝
A box with a single line emanating from it is either a literal or is requesting input from STDIN:
╔═════════════════════════════════╗ ╔══════╗
║ this is the literal number 42 ║ ║ 42 ╟────
╚═════════════════════════════════╝ ╚══════╝
╔════════════════════════════════╗ ╔══════╗
║ this box requests user input ║ ║ ╟────
╚════════════════════════════════╝ ╚══════╝
"Rotation-invariant" means that the above 42
can be written as
│
╔══════╗ ╔══════╗ ╔══════╗ ╔═══╧══╗
║ 42 ╟─── ───╢ 42 ║ ║ 42 ║ ║ 42 ║
╚══════╝ ╚══════╝ ╚═══╤══╝ ╚══════╝
│
...and it means the same thing (a literal number 42
) in each case. Data "flows" out of boxes like this and into the "lines" connecting boxes, and "loose ends" indicate that data should be written to STDOUT. So each of the four boxes above writes 42
, converted to the character *
, to STDOUT. (Although technically, these must be four separate programs, because an individual Funciton program can only have a single output.)
The lines (or "wires") aren't passive in Funciton, and T-junctions define splitters, when the input comes in as the perpendicular line of the T-junction...
╔══════╗ │ ╔════════════════════════════════════════════╗
║ 42 ╟───┤ ║ Each output line carries the value `42`. ║
╚══════╝ │ ╚════════════════════════════════════════════╝
...as well as NAND
gates, when the output is the perpendicular line:
╔══════╗ ╔══════╗ ╔═══════════════════════════════════╗
║ 42 ╟──┬──╢ 25 ║ ║ Output is (42 NAND 25) or `55`. ║
╚══════╝ │ ╚══════╝ ╚═══════════════════════════════════╝
Using just the splitter and the NAND
gate, we can define NOT
, AND
, OR
, and XOR
, which allow us to then define any additional conceivable functions:
┌──────────────────────┐
╓─────╖ ╓─────╖ ╓────╖ │ ╓─────╖ │
║ not ║ ┌──╢ and ╟──┐ ┌──╢ or ╟──┐ ├──╢ xor ╟─────┐ │
╙──┬──╜ │ ╙─────╜ │ ┌┴┐ ╙────╜ ┌┴┐ │ ╙─────╜ ┌┐ │ ┌┐ │
│ └─────┬─────┘ └┬┘ └┬┘ └───┬──────┤├──┴──┬─┤├─┘
┌┴┐ ┌┴┐ └────┬─────┘ │ └┘ │ └┘
└┬┘ └┬┘ │ └────┬────────┘
│ │ │
If Funcitown sounds interesting to you, I suggest you check out its esolangs wiki page, or, just marvel at this implementation of "99 bottles of beer", written in Funciton.
#14. ///
Related: Thue
/// (pronounced "slashes") is a language where all computation is performed via ed-style string substitution. The only "syntax" the language has is a single construct, formed using the forward slash /
character, which is used to define string replacements of the form:
/pattern/replacement/initial
The initial
string is searched for the pattern
, which is removed and replaced with the replacement
. This search-and-replace procedure is then repeated, again, from the beginning of the new (modified) string. If the pattern
cannot be found in the string, then the initial
(or newly-modified) string is printed to the console and the program terminates.
For example:
/NAME/Karl Hungus/Hello, NAME!
The above /// program will search the string Hello, NAME!
for the substring NAME
, which, when found, it will replace with the string Karl Hungus
:
/NAME/Karl Hungus/Hello, Karl Hungus!
After a single iteration, the substring NAME
can no longer be found in the modified string, so the program terminates, printing Hello, Karl Hungus!
to the terminal.
There is only a single other special character in /// and that's the backslash \
character, which can be used to escape the /
character as well as itself. Any program which contains no /
or \
characters is trivially a quine, printing its source code to the console.
A more difficult quine in /// is one which only contains the \
and /
characters (leaning toothpick syndrome to the extreme):
/\/\/\/\\\\/\\\\\\\/\\\\\\\/\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\//\/\/\/\\\/\/\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\////\\\///\\////\\\///\\\///\\////\\////\\////\\////\\\///\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\////\\////\\////\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\////\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\////\\////\\////\\////\\\///\\////\\////\\\///\\////\\////\\\///\\////\\\///\\////\\\///\\////\\\///\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\////\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\////\\////\\////\\////\\\///\\////\\\///\\////\\\//\/\/\/\\\/\\\/\\////\//\//\/\/\/\\\\/\\//\\\/\\\/\\\/\\\\\\\/\\\\\\\/\\\/\\\\////\//\//\/\/\/\\\\/\\\/\\\/\\\/\\\\\\\\\\////\/\/\
/// was indirectly shown to be Turing-Complete by Ørjan Johansen, who used the language to create an interpreter for a different esolang, Bitwise Cyclic Tag, which is itself Turing-Complete.
#15. Factory
Factory is a really interesting language, where your commands move a "claw" around the "byte factory". You can pick up 1
s and 0
s with the claw, move them into storage spaces, and create "shipments" of bits that are grouped into 8-bit bytes and "delivered" to the standard output as ASCII characters. Factory program files have the .claw
extension, for obvious reasons.
The byte factory looks like this initially:
|
|
/ \
\ /
[1] | _____________ | _____________ | _____________ | X | [:=:] | [ ] | !!!!!!!! | &&&
production |storage space 1|storage space 2|storage space 3| garbage | shipping | supply | Invertor | and
The different rooms have different purposes:
production
creates a constant stream of1
s at the start of the program, but can be changed to a stream of0
s if a0
is "dropped" into the room from the claw (dropping a1
switches production back to a stream of1
s)- the
storage space
s each hold a stack of bits. Bits dropped from the claw are added to the top of the stack and the claw can pick up the stack at any point, carrying that bit and all bits above it. - bits dropped into the
garbage
are destroyed and lost forever shipping
works like astorage space
, until the bits are delivered to STDOUT as ASCII characterssupply
receives input characters from the user, which are converted to bits and stored as a stack in reverse order (so the first bit of the first character is at the top of the stack)- the
invertor
accepts a single bit which it inverts (0
becomes1
and1
becomes0
) - the
and
room accepts two bits, destroying one of them. If either bit is a0
, the other bit is destroyed so only a0
remains
The programmer instructs the claw to move around the factory, picking up and dropping bits and stacks of bits into the various rooms:
<
tells the claw to move left one room (if the claw is in theproduction
room already, it will not move)>
tells the claw to move right one room (if the claw is in theand
room already, it will not move)v
tells the claw to drop all of its bits into this room, if it is carrying any, and pick up the top bit in this room otherwiseO
ships the contents of the shipping roomI
asks for an input into the supply room- and so on...
Factory is a really neat creation that's half game, half programming language. I would love to see a Factory debugger that actually shows the claw moving around the factory, picking up bits and dropping them off in different locations. It's probably not the most useful programming language, but it's definitely unique.
#16. golfing languages
For these next few entries, I'd like to discuss a few broader categories of languages, rather than individual languages themselves. The first category I'll start with is golfing languages.
Golfing languages are used in code golf, a competition where users try to write a program with the smallest source code possible, usually measured in bytes. Code Golf Stack Exchange (CGSE) is a vibrant community of programming language enthusiasts who use mainstream and esoteric languages alike. APL is a common language for code golfing, though many languages were specifically created for golfing, including:
...and many more. I've grouped J and Jelly together because the developers behind Jelly say they were influenced primarily by the J programming language, and J was designed by... Kenneth E. Iverson, creator of APL. You can find these and many more golfing languages listed on CGSE's Showcase of Languages thread.
To give you a taste of what code golfing is like, here's a challenge to write a program which can detect palindromes, that is, strings which are read the same forwards and backwards. It doesn't matter how the program accomplishes this, but it needs to somehow indicate when input passed to it is palindromic or not. For reference, a minimal-ish palindrome-detecting program written in Java might look like:
import java.util.*;
public class P {
public static void main (String a[]) {
String o, r = "";
Scanner s = new Scanner(System.in);
o = s.nextLine();
for (int i = o.length() - 1; i >= 0; i--)
r = r + o.charAt(i);
System.out.println(o.equals(r));
}
}
I've left whitespace in for clarity, but in a real code golf competition, we would compress this to:
import java.util.*;public class P {public static void main(String a[]){String o,r="";Scanner s=new Scanner(System.in);o=s.nextLine();for(int i=o.length()-1;i>=0;i--)r=r+o.charAt(i);System.out.println(o.equals(r));}}
...and count the bytes in the solution. Since these are all ASCII characters, the number of bytes is simply the number of characters and my solution in Java has 216 bytes. How about some of these golfing languages?
Here's a solution in Brachylog (3 bytes):
I↔I
...here's one in Jelly (5 bytes):
ḂŒ
ŒḂ
...and 05AB1E (3 bytes):
ÂQÂ
...J (15 bytes):
-:|.NB. .BN.|:-
...GolfScript (11 bytes):
.-1%=#=%1-.
...and Dyalog APL (6 bytes):
⌽≡⊢⊢≡⌽
My solution suddenly looks much less impressive in comparison. You can see that most of these golfing languages use UNICODE characters extensively in their source code: a single character can encode a hugely complex operation, so using a code golf language usually means simply memorizing what lots and lots of individual characters do. If you're interested in code golfing, I recommend you check out the Code Golf Stack Exchange, or join a local in-person code golfing competition (usually, these are restricted to a single language or a pre-defined set of languages).
#17. languages with 2-dimensional source code
As most natural, written languages are read only in one direction (in English, left-to-right) and "wrap" around the edge of a page, it's intuitive that programming languages should do the same thing. But some language designers have decided to make "better" use of the 2D space in which these languages can be written and displayed, allowing source code to be read left-to-right, top-to-bottom, or diagonally. This wider variety of reading directions has led to creations like:
...among others. These languages usually include constructs which change the direction in which the code should be read, much like Piet's "walls" of black pixels.
Re:direction only uses UNICODE arrows (◄, ▲, ►, ▼) to direct program flow and add those directions to a queue, plus a single instruction for popping directions from the queue (♦), which can allow for looping and control flow. Output from the program can only be integers, but those integers can be interpreted as ASCII characters. For example, here's a "Hello, World!" program written in Re:direction, which you can try out here!
In Hexagony and Beeswax, code is written on a hexagonal grid of fixed-width characters. A "Hello, World!" program in Hexagony might look like:
H ; e ;
l ; d ; *
; r ; o ; W
l ; ; o ; * 4
3 3 ; @ . >
; 2 3 < \
4 ; * /
...and a program to print the N
-th Fibonacci number in Beeswax might look like:
;{#'<>~P~L#MM@>+@'p@{;
_`n`TN`F(`{`)=`X~P~K#{; d~@M<
Beeswax provides additional complexity by allowing the programmer to summon "bees", which act as pointers, moving around the program in various directions and completing tasks independently of one another.
In Maze, the program's source code looks like... a maze:
##,##,## // fibonacci
##,##,^^,##,##
##,..,<>,PP,##
##,..,##,..,##,##,##,##,##,##,##,## // left column is fib(n), right column is fib(n+1).
##,##,##,##,##,%D,..,LD,..,**,..,..,..,..,..,## // the small left loop sets fib(n) to 0; simultaneously,
##,..,..,..,##,>>,##,..,## ##,##,##,##,##,..,## // the small right loop sets a clone of fib(n+1) to fib(n+1)+f(n).
##,MM,##,..,##,..,##,..,##,##,..,..,..,##,..,## // (this technique is similar to brainfuck [->+<])
##,..,**,FL,..,02,##,%R,..,##,..,##,PP,##,..,## // the small loop at the bottom does nothing, but make sure
##,##,##,NL,##,##,##,%D,<>,01,FR,..,..,##,..,## // that the original fib(n+1) is synchronized with the other cars.
##,>>,##,##,##,..,##,##,03,##,##,##,..,## // then fib(n+1) goes to left column and fib(n+1)+fib(n) to right column
##,(),##,..,..,FM,..,..,%R,..,..,..,..,##
##,##,##,..,##,..,##,##,##,##,##,##,##,##
##,..,..,..,##
##,##,##,##,##
PP-> +=1
MM-> -=1
FR-> IF ** THEN %U ELSE %D
FL-> IF ==0 THEN %D ELSE %L
FM-> IF ** THEN %L ELSE %R
LD-> IF ** THEN %L ELSE %D
NL-> ="\n"
In this language, "cars" are spawned from the starting position ^^
, of which there can be only one per "map". Commas ,
are used to separate "cells" of the program and every cell is a two-character sequence. Cars cannot move through walls ##
, but instead follow the path ..
and have actions performed on them by functions, which are composed of two capital letters and are defined within the source code but outside of the maze, as seen above (PP
, MM
, etc.).
Oliver Faircliff has even designed this nice, animated Maze interpreter in C++ which looks more like a low-budget smartphone game than a programming language.
There are a huge variety of two-dimensional (and higher-dimensional) programming languages out there and many are quite a bit more complex than arrows directing the flow of the program. For example, the (as-yet-unimplemented) language Infinite Dimensional Tengwar Meltdown (IDTM) is an esoteric language written in the Tengwar script from Lord of the Rings. It's an infinite-dimensional, pointer-based language where data exists on an array of infinite size and code decays via entropy over time (see also: Entropy). So loops, which are run multiple times, will degrade and change their meaning over the course of the program.
Just when you thought esoteric languages couldn't get weirder.
#18. languages which emphasise source code aesthetics
When you think of the aesthetics of source code, you probably think about whitespace. The visual structure of a program is largely defined by blocks of code, blank lines, indentation, and more. You might not think about how the characters of the source code can affect its aesthetic properties. For instance, characters with lots of curves can give a "wavy", "bubbly", or "smooth" appearance:
s@Ss@S$3CO0oc896$3Cs@S$3CO0oc896O0os@S$3CO0oc896c896
...while characters with lots of straight lines can communicate "jaggedness", "sharpness", or "clutter":
/\|EL/H>+-_=IT\MN|F#^<ZK/k\vx|/>+V|Xzw/WF#^<ZK/k\vx|/>+-_=\
Some language designers have indeed thought about the aesthetic properties of certain characters and have used them to achieve a particular goal with their languages. For instance, the creator of Grass wanted to make a language where the source code looks like an unkempt lawn. All Grass source code is written using only the characters w
, W
, and v
:
_, ._
( ・ω・) んも〜
○={=}〇,
|:::::::::\, ', ´
、、、、し 、、、(((.@)wvwwWWwvwwWwwvwwwwWWWwwWw
wWWWWWWwwwwWwwvwWWwWwwvwWWW
作ってみたwwwww
とりあえず公開wwwwwwwっうぇ
Other language designers require their source code to resemble some kind of ASCII art, like DNA# (a play on C#), which has source code that looks like DNA double-helices:
AT
T--A
A----T
T-----A
T-----A
G----C
T--A
GC
CG
C--G
A----T
A-----T
T-----A
A----T
A--T
GC
AT
C--G
T----A
C-----G
T-----A
G----C
C--G
CG
...
If you're interested in these kinds of languages, there are many descriptions for as-yet-unimplemented programming languages like these over at esolangs.org, including:
...Cactusi, whose source code should look like cactuses in a desert (or the Google Chrome dinosaur game)
|| ||
==|| =||=
_____||____||____
...Tree, which is meant to look like, well, a tree (or a shrub of some kind):
^
^^|^^
^^\|/^^
H^ |/^^^
\| e
|/
ol~|
\|
, 32|
\/ |
\ | W
l \| /
\ d |/ o
\/ !|r /
\/ |\/
\ |/
\|
...or Rotary, a BF derivative where source code must be written in circles:
!!!,.v
!!! !!!
! !
! !
! !
! !
! !
!!! !!!
!!!!!!
!!!,.^
!!! !!!
! !
! !
! !
! !
! !
!!! !!!
!!!!!!
"Source code as art" is certainly a concept that is alive and well, at least among the esolang community.
#19. languages built so that the source code looks like ___
In a slightly different category from those languages in #18 are the following languages, which are written using reduced character sets, or add lots of extra "decoration" in an attempt to make the language look like...
a recipe
The Chef programming language (not to be confused with the Chef configuration management tool), is a language designed so that its source code looks like a recipe. Here's a "Hello, World!" program in Chef:
Hello World Souffle.
This recipe prints the immortal words "Hello world!", in a basically brute force way. It also makes a lot of food for one person.
Ingredients.
72 g haricot beans
101 eggs
108 g lard
111 cups oil
32 zucchinis
119 ml water
114 g red salmon
100 g dijon mustard
33 potatoes
Method.
Put potatoes into the mixing bowl. Put dijon mustard into the mixing bowl. Put lard into the mixing bowl. Put red salmon into the mixing bowl. Put oil into the mixing bowl. Put water into the mixing bowl. Put zucchinis into the mixing bowl. Put oil into the mixing bowl. Put lard into the mixing bowl. Put lard into the mixing bowl. Put eggs into the mixing bowl. Put haricot beans into the mixing bowl. Liquefy contents of the mixing bowl. Pour contents of the mixing bowl into the baking dish.
Serves 1.
One of Chef's design principles is that "[p]rogram recipes should not only generate valid output, but be easy to prepare and delicious." Whether or not the above souflée recipe is "delicious" is, I suppose, open to interpretation, but there is a different "Hello, World!" recipe that makes a surprisingly good chocolate cake.
Braille
Louis Braille is the inventor of the tactile writing system for the visually impaired now known commonly as braille (all-lowercase), but he also lends his surname to the programming language Braille (capitalised).
Braille (the programming language) is written using only the UNICODE braille codes (U+2800 to U+28FF). As there are 256 codes (written on a 2x8 grid), the creator of Braille (Brian McPherson) decided to arrange them in a 16x16 grid, where there are 16 actions that can be performed along with a single hexadecimal digit passed to that action.
Here's a Braille program that prints "Hello, World!" in ASCII characters:
⠆⠄⡒⡆⡘⠀⢐⠊⠦⢦⠗⢾⠿⠂⢢⢾⢦⢦⠮⢄
And a "Hello, World!" that prints its output in braille:
⠆⡆⢤⡔⠈⠖⠙⠇⠗⠕⠺⠀⠂⠕⠇⠇⠑⠓
a play
The (in)famous Shakespeare language adds lots of extra decoration to the source code so that it resembles one of the plays of its namesake. The language's creators summarise it as follows:
"The characters in the play are variables. If you want to assign a character, let's say Hamlet, a negative value, you put him and another character on the stage and let that character insult Hamlet.
Input and output [are] done be having someone tell a character to listen [to] their heart [or] speak their mind. The language contains conditionals, where characters ask each other questions, and jumps, where they decide to go to a specific act or scene. Characters are also stacks that can be pushed and popped."
There's a "Hello, World!" written in Shakespeare that's just a bit too long to reproduce here, but here's a program which takes any input, reverses it, and prints the reversed string:
Outputting Input Reversedly.
Othello, a stacky man.
Lady Macbeth, who pushes him around till he pops.
Act I: The one and only.
Scene I: In the beginning, there was nothing.
[Enter Othello and Lady Macbeth]
Othello:
You are nothing!
Scene II: Pushing to the very end.
Lady Macbeth:
Open your mind! Remember yourself.
Othello:
You are as hard as the sum of yourself and a stone wall. Am I as
horrid as a flirt-gill?
Lady Macbeth:
If not, let us return to scene II. Recall your imminent death!
Othello:
You are as small as the difference between yourself and a hair!
Scene III: Once you pop, you can't stop!
Lady Macbeth:
Recall your unhappy childhood. Speak your mind!
Othello:
You are as vile as the sum of yourself and a toad! Are you better
than nothing?
Lady Macbeth:
If so, let us return to scene III.
Scene IV: The end.
[Exeunt]
rock lyrics
The Rockstar language is designed so that its source code looks like lyrics to a cheesy 80s rock ballad. It was created by Dylan Beattie in 2018, inspired by a tweet which suggested that someone should develop a language called Rockstar to confuse recruiters, who are always looking for "rockstar developers" for their clients.
Here's FizzBuzz in Rockstar:
Midnight takes your heart and your soul
While your heart is as high as your soul
Put your heart without your soul into your heart
Give back your heart
Desire is a lovestruck ladykiller
My world is nothing
Fire is ice
Hate is water
Until my world is Desire,
Build my world up
If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing
Shout "FizzBuzz!"
Take it to the top
If Midnight taking my world, Fire is nothing
Shout "Fizz!"
Take it to the top
If Midnight taking my world, Hate is nothing
Say "Buzz!"
Take it to the top
Whisper my world
fetish erotica
Last but not least is Fetlang, a very NSFW language whose source code resembles fetish erotica, and is "licensed under the BSDM (BSD, modified) license".
Here's a relatively tame Fetlang program that just echoes the arguments passed to it:
Make Sean moan
Worship Carrie's feet
Bind Amy to Saint Andrew's Cross
Have Amy hogtie Sean
If Amy is Carrie's bitch
Make Slave scream Sean's name
Make Sean moan
It only gets more risqué from there.
#20. Q#
"The future is quantum", asserted IBM in a 2017 blog post, which conveniently touted their own quantum computer, the IBM Q. The theoretical foundations of quantum computing were laid by Paul Benioff, Richard Feynman, and many others in the early 1980s, but it's only recently that engineering has caught up to theory and the construction of quantum computers like the IBM Q has become possible.
Quantum computing offers immense advantages over traditional (classical) computing in particular domains like cryptography, physical simulations, and highly-parallelisable problems like solving systems of equations. Recently, Google proclaimed quantum supremacy with an algorithm that ran on their 54-qubit Sycamore quantum processor in just 200 seconds. An equivalent algorithm would require 10,000 years of processing time on a state-of-the-art classical supercomputer, rendering it practically impossible.
Programming a quantum computer is entirely different from programming a classical computer, because quantum effects like entanglement, coherence, and uncertainty come into play. Even at the most fundamental level, quantum programming differs from classical programming. The traditional logical AND, OR, and NOT gates are replaced by Hadamard gates, Toffoli gates, and Pauli X, Y, Z gates. It is not a matter of simply learning a new programming language to learn quantum computing, but rather like learning an entirely new, extremely difficult skill (with a lot of mathematics and physics behind it).
Still, Microsoft has attempted to make the transition from classical programming to quantum programming as smooth as possible with their Q# programming language, first released to the public in late 2017. Q# joins Microsoft's "sharp" family of programming languages, preceded by C# and F#. There are extensions for Q# for Microsoft's Visual Studio and VS Code IDEs, which are packaged with quantum simulators (since most people don't yet have access to actual quantum computers).
Q# code looks quite similar to C# code, and Microsoft have provided lots of helpful documentation and examples for you to get started. Because Q# is designed to run on actual quantum computers, it is usually run from within another language (like Python or C#), and the quantum simulator from that language interacts with Q#.
For example, here's a bit of Q# code, that -- when called within C# host code -- will measure the value of one of a pair of entangled qubits, followed by the second one. The same value will always be returned due to the entangled state:
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int) {
mutable numOnes = 0;
mutable agree = 0;
using ((q0, q1) = (Qubit(), Qubit())) {
for (test in 1..count) {
Set(initial, q0);
Set(Zero, q1);
H(q0);
CNOT(q0, q1);
let res = M(q0);
if (M(q1) == res) {
set agree += 1;
}
// Count the number of ones we saw:
if (res == One) {
set numOnes += 1;
}
}
Set(Zero, q0);
Set(Zero, q1);
}
// Return number of times we saw a |0> and number of times we saw a |1>
return (count-numOnes, numOnes, agree);
}
Programming languages, like real-world languages, come in a wide variety of shapes and forms. Not every language needs to be declarative, or functional, or object-oriented. A language doesn't even need to have the ability to define named variables or functions in order to be able to compute anything you throw at it. There are a huge range of possibilities, as the above list attests to.
If you're as fascinated with programming languages as I am, I recommend you pay a visit to esolangs.org, where you can learn more about these and many other esoteric languages. If you're interested in creating your own programming language, watch this space. I hope to put out a guide within the next few months on developing your own language and compiler from scratch!
If you liked what you read above, you should follow me on Dev.To or Twitter to get more of that sweet, sweet content. If you really liked it, maybe you could support me by donating just a few of your country's currency units to me at Ko-Fi.
Whatever you do, thanks for reading!