dc is one of the oldest unix utilities, and is part of almost every distribution. DC stands for Desktop Calculator, but as well as offering a command line reverse polish calculator, it’s really a programming language in its own right.

dc is a stack based programming language, and is as terse as possible. Almost all operations are a single character, and whitespace is only needed to separate numbers from each other. As a taster, here’s a program which prints out the numbers 1 to 100:

[p1+d101>A]sA1lAx

Let’s break this down:

[p1+d101>A] #Put 'p1+d101>A' in a string on the stack
sA	    #Store the top of the stack (the string we just created) in register 'A'
1	    #Store the number 1 on the stack
lAx	    #Load the register 'A' and execute it.

So the lines after the initial string are just responsible for storing it in register ‘A’, pushing an initial 1 onto the stack, then executing what we’ve just stored in register ‘A’. The main work is done inside the string we store in register ‘A’.

Now let’s break down that first string:

[      #Denotes the start of a string
p      #Print the value on the top of the stack
1      #Push the value 1 onto the stack
+      #Add the top two values on the stack
d      #Duplicate the top of the stack
101    #Push 101 onto the stack
>A     #If the second top value is greater than the top, execute register 'A'
]      #End of the string

So this string prints the value on the stack, adds one to it and then if it’s less than 101, it executes register ‘A’ again, so forming a loop. The d in character 5 duplicates the top of the stack because the conditional operator > consumes both of its arguments from the stack, and we need the counter to be on the stack for the next invocation of register ‘A’.

That’s just a very simple example of what you can do with dc that you couldn’t do with a normal calculator. Here’s another, slightly more involved example.

dc macros like the one above can be passed functions in much the same way as with more sophisticated programs. Any function can be put on the stack or stored in a register, and anything on the stack or at the top of a register is visible to other functions which can then invoke them.

We can use this to write functions which take other functions as arguments. The function below takes a function from the top of the stack, and applies it to each remaining element of the stack, storing the results in a temporary register before pushing them back onto the stack at the end.

[SX0Si                 #Store the top of the stack in 'X', store 0 in 'i'
[lXxSALi1+Si]sL        #Store in 'L' a string which runs 'X', pushes the result to A and increments i
[lLx1z>B]sB            #Store in B a string which executes 'L', and re-executes 'B' if the size of the stack >1
lBx                    #Execute 'B'
[LALi1-dSi0<B]sB       #Store in 'B' a string which loads 'A', decrements i and re-executes 'B' if 0<i
lBx                    #Execute 'B'
]sS                    #Store the whole thing in 'S'

To show the brevity (and unreadability) of dc, the whole thing can be written as one line with no whitespace at all:

[SX0Si[lXxSALi1+Si]sL[lLx1z>B]sBlBx[LALi1-dSi0<B]sBlBx]sS

This function gets stored in register ‘S’, so to create a stack with the numbers 1 2 3 4, and a function which squares those numbers, we would write the following:

1 2 3 4 [d*] lSx

This function doesn’t print anything out - there are no ‘p’ calls. [d*] squares each number (duplicates it then multiplies the two numbers together). The results are on the stack, and can be seen by typing ‘f’ to see the full stack:

f
16
9
4
1

There’s a lot more you can do with dc. It’s arbitrary precision, you can control the input and output radix, accept input from the user whilst executing and more. I hope to put together some more articles about these features soon, but in the mean time, the manual and the Wikipedia page are good places to find out more.