Exploring concatenative combinators.

As I read and tried to digest Brent Kerby’s The Theory of Concatenative Combinators, I wrote a simple tool called Concom so that I could try the examples out as I went along. It’s a purely symbolic program, and its syntax exactly matches what is given in the paper, with the addition of comments and definitions. It’s a perfect companion to experiment with. If you want to just dive in, head over to the project page for source downloads.

For the uninitiated, a combinator is basically a function that applies some sort of transformation to the data stack. There are no variables, all data is stored on the stack and is manipulated by the combinators. For a good description of a concatenative language and some background information, check out the concatenative.org wiki.

Concom is a basic concatenative language interpreter, and only has 9 primitive words, including the first 8 presented in the paper. The available words at startup are swap , dup , zap , empty , unit , cat , cons , i , and dip . The non-combinator words are show , which shows the stack, and exit , which exits the interpreter. All words are in lowercase, while all symbols are in uppercase. Symbols are the pieces of data manipulated on the stack. Comments begin with the octothorpe ( # ). The sections of code between the square brackets ([, ]) are called quotations. They are complete and valid Concom programs, and for all intents and purposes they are anonymous functions. They can be pushed to and manipulated on the stack just like a symbol.

If for whatever reason you find yourself needing to define your own words, the familiar Forth/Factor syntax is available. A word definition starts with a colon ( : ), the name of the word, the body of the word, and a terminating semicolon ( ; ) Here’s an example definition of the k combinator:

# [B] [A] k == A : k [zap] dip i ;

Concom has a REPL, so your definitions are persistent within your session. The best (and most fun) way to learn is to try to implement the combinators discussed in the paper from some restricted set of words, the later sections of the paper covers that almost exclusively. Here’s my attempt at the s combinator with just the Concom primitives:

# [C] [B] [A] s == [[C] B] [C] A : s [unit] dip [cons] dip swap dup i cons swap i zap [] cons cons dip i ;