The elegant minimalism of Forth is inspiring-- how many other languages can fit their REPL and development environment into a few kilobytes?<p>However, I find implicit arity to be the largest barrier in reading concatenative programs.<p>To understand what a line of Forth code does, you need to understand both what each function does, and how it manipulates the stack to accomplish it. That's more memory pressure than an imperative language like C, where the flow of data and computations is obvious. It's exacerbated by the tendency to factor a single function into many simpler ones.<p>In a team, the increased memory burden also requires more communication for shared understanding of code.<p>Many concatenative languages eventually grow support for local variables, since it's _incredibly_ awkward to implement certain algorithms when you have to do stack juggling to use a variable in a computation.
Forth is brilliant, but my favourite concatenative language is PostScript. Most view PostScript as nothing more than a dated binary format for vector graphics. However, writing plots and diagrams in pure PS is incredibly flexible and pretty easy once you build up or find enough libraries to do what you want. Postscriptbarcode[0] is an example of a good library. [1] is a good guide to writing PS by hand.<p>What is PS does lack, however, is a modern debugger (or interpreter with decent error reporting) and package management.<p>[0] <a href="http://code.google.com/p/postscriptbarcode/" rel="nofollow">http://code.google.com/p/postscriptbarcode/</a>
[1] <a href="http://www.math.ubc.ca/~cass/graphics/manual/" rel="nofollow">http://www.math.ubc.ca/~cass/graphics/manual/</a>
One thing I did in the past with concatenative programming that was very fun to work with, was an engine of genetic programming. Among the other features of concatenative programming languages there is that it is trivial to create a random program that is valid, and also to mix different programs together. Not that doing genetic programming with s-expressions is so hard, but it is definitely possible to create very simple and fast implementations with CP.
Warning: Shameless self promotion<p>I implemented a concatenative DSL for Clojure called Factjor [1] inspired by Factor [2]. Clojure is to Lisp what Factor is to Forth. I used Factjor to implement DomScript [3], which is sorta like jQuery re-imagined as a concatenative language like PostScript. I also gave a talk on both Factjor and DomScript at Clojure/West. Slides are available now [4] and a video will be available on InfoQ soon.<p>[1] <a href="https://github.com/brandonbloom/factjor" rel="nofollow">https://github.com/brandonbloom/factjor</a><p>[2] <a href="http://factorcode.org/" rel="nofollow">http://factorcode.org/</a><p>[3] <a href="https://github.com/brandonbloom/domscript" rel="nofollow">https://github.com/brandonbloom/domscript</a><p>[4] <a href="https://github.com/strangeloop/clojurewest2013/raw/master/slides/sessions/Bloom-Concatenative_Clojure.pdf" rel="nofollow">https://github.com/strangeloop/clojurewest2013/raw/master/sl...</a>
Very important article! Preach it.<p>I remember discovering the Joy language (and combinatory logic) and being blown away by the elegance of being able to express programs just by composing functions. It was a pretty big epiphany to learn that when functions pop arguments from and push results onto a stack, the "application of a function to a data value" could be treated equivalently to "composition of a function with a 'constant' function that pushes a data value onto a stack". That led to the subsequent discovery that the data stack is extra "scaffolding" that can be removed: using prefix notation instead of postfix allows the program to be represented in memory as an actual composition of partially applied functions, each of which takes the remainder of the program as an argument and returns an output program. This led to the creation of Om [1], which I believe is the "most concatenative" language for this reason.<p>[1] <a href="http://om-language.org" rel="nofollow">http://om-language.org</a>
The only thing that bothers me about the concatenative languages I've seen is the stack. It is a global variable. You don't have the bounding (this is your part of the stack) that you have in languages that have an enforced frame for procedure/method calls.<p>Sometimes I wonder what a concatenative language would look like if operations could only access things given them by the immediately previous operation and if those things were read-only.
<i>This is impossible to do with any other type of language. With concatenative programming, a parallel compiler is a plain old map-reduce!</i><p>This statement (in context) draws a defining line around what is and isn't concatenative, and the statement by Norman Ramsey should have been refuted succinctly with a derived definition: Composable expressions with associativity.
This would be much better reordered. The lead 'why concatenative programming matters' is only answered halfway through, after the reader is expected to trudge through lambda notation. Why it matters: it's the basis for interpreters of languages you use. Then explain why, then explain what it is.
I especially liked the comparison with unix pipes. Whereas Powershell is kind of an attempt to make command line scripting OOP. This could be applied to create the next generation of unix shells...<p>I'll have to think about this.