/r/concatenative
Discussion of concatenative programming, a paradigm of compositional functional languages.
Anything related to the use, theory, or implementation of concatenative programming languages.
Discuss
Related Subreddits
/r/concatenative
I was visiting a building of a large IT company and noted that they named the meeting rooms after programming languages. These did not only include Lisp, XSLT and Plankalkül, but also Joy. As concatenative languages are often seen as really obscure, this made me happy. Seems we're no more obscure than Plankalkül now!
A presentation at the Strange Loop Conference on "Concatenative programming and stack-based languages" by Douglas Creager: https://www.youtube.com/watch?v=umSuLpjFUf8
Concatenative languages use implicit argument passing to provide a concise expression of programs comprising many composed transformation functions. However, they are sometimes regarded as “write-only” languages because understanding code requires mentally simulating the manipulations of the argument stack to identify where values are produced and consumed. All of this difficulty can be avoided with a notation that presents both the functions and their operands simultaneously, which can also ease editing by making available values and functions directly apparent. This paper presents a two-dimensional notation for these programs, comprising alternating rows of functions and operands with arguments and return values indicated by physical layout, and a tool for interactive live editing of programs in this notation.
https://michael.homer.nz/Publications/PAINT2022
I often hear that a concatenative language does not need a stack. You can have a queue or something else. But could this also be taken to mean 'does not need a backing data structure'? I'm finding it hard to imagine how this is possible without term-rewriting. If every program was defined only as the adjacency/composition of terms, then there could only ever be one program state as it flows L-R. For example, how would you dup? Multiple return values? I like the idea of functions being single input, single output.
Of course, a compiler implementation could use a backing data structure, while the language design just pretends there isn't one and dup does dup because "I said so". But this is unappealing to me.
Got a question about common parameter order conventions in concatenative or stack-based languages. For context, I don't have a lot of experience writing concatenative code, but enjoy thinking about it and have made some concatenative languages in my spare time.
Are there standard ways of choosing the argument order for non-commutative, multiple-input functions? Much like for functional languages, where a certain parameter order can allow programmers to make use of automatic currying to reduce boilerplate.
The example I'm thinking of right now is cons
for lists. There's two different ways to write the stack effect (pardon some functional list consing notation):
e l consl -- (e::l)
l e consr -- (e::l)
Both functions yield the same result, but the parameter input order is swapped. The suffixes that I've chosen here are abbreviations of 'left' and 'right', because wrt to the output it looks like you're reading the input 'left-to-right' in the first and 'right-to-left' in the second.
Is this even a problem that comes up frequently? I'm really interested in which stack effect is preferred from a 'noisy stack-shuffle code reduction' point of view, but if it's rarely a problem that would be very interesting to know too.
Do concatenative languages generally provide both versions, with some common naming convention to distinguish? Does consistent usage of one of the two make things easier for most use cases, so there is no need for both? I personally suspect the first behaves similar to automatic currying in functional languages, and would be great for use in higher order functions, while the second might be preferred in iterative/for-loop based code. Is there no standard for this sort of thing at all? Does Forth, say, do it differently than Factor?