
Why Concatenative Programming Matters (2012) - jasondenizac
http://evincarofautumn.blogspot.mx/2012/02/why-concatenative-programming-matters.html
======
Scaevolus
The elegant minimalism of Forth is inspiring-- how many other languages can
fit their REPL and development environment into a few kilobytes?

However, I find implicit arity to be the largest barrier in reading
concatenative programs.

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.

In a team, the increased memory burden also requires more communication for
shared understanding of code.

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.

~~~
evincarofautumn
This is true, but it’s also important to realise that Forth is not the only
direction. ;)

It’s been a while since I wrote this article, and there are a number of things
it doesn’t address, such as the practical concerns you mention. It’s much the
same issue as comes up when dealing with large assembly projects, or
dynamically typed ones for that matter. Knowing what’s going on can be
difficult to discern without a deep understanding of the overall system, and
bugs have a tendency to hide in obscure places.

And speaking of assembly, Forth _is_ essentially assembly code for a virtual
stack machine. Or an actual stack machine.

I’ve been idly working on a statically typed concatenative language for a long
time now, partly because I intend it to be taken seriously sometime in the
next decade, but mostly as a learning experience. It’s designed to address
many of these concerns—particularly, enabling programmers to focus on data
flow by framing it as a functional language. (E.g.: don’t shuffle stacks—use
combinators and/or locals.)

However, I continually run into problems with the type system. Typing of
concatenative languages is not well researched and is surprisingly difficult.
I’m not a type theorist by any means, but at this point I’m probably the world
expert on concatenative type systems, simply because there are so few people
working on the problem. If anyone would like to help out, I’d love to chat by
email (username@gmail).

~~~
qznc
Cat is concatenative and statically-typed. <http://www.cat-language.com/>

~~~
evincarofautumn
Sure is. Its type system just suffers from some limitations that I’d like to
remedy in my own language.

------
saljam
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.

What is PS does lack, however, is a modern debugger (or interpreter with
decent error reporting) and package management.

[0] <http://code.google.com/p/postscriptbarcode/> [1]
<http://www.math.ubc.ca/~cass/graphics/manual/>

~~~
colanderman
I went on a PostScript kick a few years back. It's amazing what you can tell
printers to do: <http://fstutoring.com/~chris/postscript/>

------
antirez
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.

~~~
gnosis
You might be interested in taking a look at PushGP:

<http://faculty.hampshire.edu/lspector/push.html>

------
snprbob86
Warning: Shameless self promotion

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.

[1] <https://github.com/brandonbloom/factjor>

[2] <http://factorcode.org/>

[3] <https://github.com/brandonbloom/domscript>

[4]
[https://github.com/strangeloop/clojurewest2013/raw/master/sl...](https://github.com/strangeloop/clojurewest2013/raw/master/slides/sessions/Bloom-
Concatenative_Clojure.pdf)

------
sparist
Very important article! Preach it.

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.

[1] <http://om-language.org>

------
michaelfeathers
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.

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.

~~~
abecedarius
One thing it could look like is Backus's FP. I made a concatenative variant of
it back in the 80s, and just rewrote the essentials this afternoon:
<https://github.com/darius/peglet/blob/master/examples/fp.py>

In my earlier dialect I added a form of local variables, just enough for
better readability without really changing the semantics.

------
smosher
_This is impossible to do with any other type of language. With concatenative
programming, a parallel compiler is a plain old map-reduce!_

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.

------
tmcw
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.

~~~
mjn
For some audiences I'd agree, but I think the current presentation works well
if the target audience is people who already believe that functional
programming matters, but are skeptical that concatenative programming is an
interesting or important concept. For that audience I think the presentation
starting from the familiar type-signature notation is effective.

------
AlexanderDhoore
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...

I'll have to think about this.

~~~
beatgammit
Hmm, interesting. I've been thinking about a Haskell-based shell, but the flow
of concatenative programming might be a better fit. Maybe I'll have to play
with this idea this summer as well...

------
elliotlai
You meant Arrows <http://www.haskell.org/arrows/>

~~~
evincarofautumn
I might be wrong, but I think a concatenative language can’t be represented
using only arrows, because arrows aren’t sufficient to express dynamic
function application. You can think of monads as arrows with the “bind”
function of a type like (a × (a → b) → b). That’s precisely the type of the
common concatenative “apply” combinator that lets you do anything useful. The
lifting of application is what allows you to treat terms (objects) as actions
(morphisms). Without it or an equivalent combinator, you can’t write context-
sensitive computations or manipulate concatenative quotations in any
meaningful way.

------
SagelyGuru
Good stuff. I never thought that the old POP-2 ideas would become fashionable
again ;)

