<p>Concatenative languages compose subprograms (nonempty sequences of terms) by appending one to the other. Most of these languages use postfix notation, like in Forth:</p>
<pre class="lang-none prettyprint-override"><code>3 4 swap add 5 mul
</code></pre>
<p>A few, like Om, use a prefix notation, where operators precede their arguments, though Om also has a novel semantics that I am not asking about here. We can imagine reversing the order of tokens in the program above:</p>
<pre class="lang-none prettyprint-override"><code>mul 5 add swap 4 3
</code></pre>
<p>and interpreting them to produce exactly the same result, with operators now preceding the expressions producing their arguments. This prefix order is more analogous to most applicative functional languages, but the semantics of juxtaposition are different, indicating function composition instead of application.</p>
<p>In some ways, the postfix notation reflects the stack-mutation semantics of Forth, administered left-to-right, while a prefix notation more illustrates composition, but these are post-facto rationalisations.</p>
<hr />
<p><strong>Are there reasons to prefer one ordering to the other?</strong> I can see no <em>technical</em> reason for these not to be equivalent, but there may be ergonomic reasons. For example, is one more readily understood by the (non-)programmer, or more efficiently written? Does one somehow enable better library design? Will editing or debugging affordances be more available with one order? Or potentially other factors I haven't considered. There may not be a firm answer one way or the other, but I'd like evidence for <em>when</em> to use each order.</p>
<p>I would be particularly interested in results of any study examining this, if there is such a thing, but learned experience from developing or using such languages would also support an answer.</p>

<concatenative-languages><language-ergonomics>
Should a concatenative language use prefix or postfix term ordering?
<p>The natural implementations are different:</p>
<ul>
<li>Postfix ordering requires a stack of only values, where operators are applied immediately, taking their operands off the stack. The execution loop for an interpreter is straightforward: read the next instruction from the program, and evaluate it.</li>
<li>Prefix ordering requires a stack which can contain both operators and values. An operator like <code>add</code> is pushed to the stack, and not evaluated until there are sufficiently many operands on the stack above it. The execution loop for an interpreter is different: read the next instruction from the program and push it to the stack; then while the top-most operator on the stack is followed by sufficiently many values for its operands, evaluate that operator.</li>
</ul>
<p>This ignores how the implementation evaluates quotes, but that is covered in <a href="https://languagedesign.stackexchange.com/q/933/89">this other question</a>.</p>
<p>It seems to me that the implementation is much simpler using postfix ordering, and this will be decisive for concatenative languages which aren't meant to be written by humans (e.g. <a href="https://en.wikipedia.org/wiki/PostScript" rel="nofollow noreferrer">PostScript</a>).</p>
<p>There is also a semantic difference which favours postfix notation: in prefix notation, each operator must take a fixed number of operands, in order to determine when the operator should be evaluated. On the other hand, postfix notation allows an operator to accept a variable number of operands, e.g. by consuming the whole of the stack.</p>
<hr />
<p>As discussed in the comments, either of these implementations could be used for either prefix or postfix order ─ you can just reverse the program's tokens to switch the ordering. However, this would give a language where the side-effects of instructions are evaluated in the opposite order to which those instructions are written. This seems undesirable to me, but in principle a language <em>could</em> be designed this way.</p>
<p>Alternatively, the language could be designed in such a way that instructions don't have side-effects, and instead a program's output is simply a value left on the stack when it terminates. Or for interactive programs, perhaps something like Haskell's <code>IO</code> monad could be used, so that the order that terms are evaluated in doesn't have to be the same as the order their side-effects are observed in.</p>
<p>So other implementations than the above two are possible, but I'll focus on these because they're straightforward, and have the desirable property that the program's side-effects are evaluated from left to right.</p>
<hr />
<p>For concatenative languages meant to be written by humans, the ease of language implementation may no longer be the deciding factor.</p>
<p>The main ergonomic difference between these two approaches is what you already identified: the syntax places functions before their arguments, which is closer to how humans think about programming. A similar issue is that a variable name can precede its initialiser, which particularly matters when the initialiser is a long expression. Here's an example using my own toy concatenative language, <a href="https://kaya3.github.io/fffff/" rel="nofollow noreferrer">fffff</a>:</p>
<pre><code>(
    n 3 % 0 = &gt;three
    n 5 % 0 = &gt;five
    (&quot;fizz&quot; print) three if
    (&quot;buzz&quot; print) five if
    (n print) three five or not if
    &quot;&quot; println
) &gt;!print_num
</code></pre>
<p>This snippet declares a quote (i.e. a user-defined function) and binds it to the name <code>print_num</code> ─ but the name doesn't appear until after the end of the quote. This is a significant readability issue. With prefix notation instead, the name would appear at the start, which would be more sensible.</p>
<p>Another ergonomic issue is in debugging. If the program is paused during execution (e.g. due to a runtime error, or hitting a breakpoint), the programmer will be able to observe the current program state. As discussed above, prefix order and postfix order have natural implementations in which the program state would be a stack of operators and values, vs. a stack of just values, respectively. It's difficult to say which of these is more useful for debugging purposes, but a stack containing operators might be preferable since it more closely resembles a stack trace in an imperative or functional language, and may give better context about what the program was doing when it was paused.</p>

CC BY-SA 4.0
2023-05-25T20:39:40.210Z
2023-05-25T22:34:56.080Z
2023-05-25T22:34:56.080Z
kaya3
CC BY-SA 4.0
2023-05-25T20:48:02.817Z
I am intrigued by what you say about implementation differences: surely it's symmetric? The compiler can reverse the tokens to get either permutation for either input, so it *ought* to be able to choose implementation and surface order independently.
Michael Homer
CC BY-SA 4.0
2023-05-25T20:51:52.260Z
@MichaelHomer It can reverse the tokens and execute that way, if you don't mind your program's side effects being executed in reverse order. `println "Hello" println "World"` in prefix notation would be reversed into a postfix program which prints "World Hello". I expect most programmers *would* mind this!
kaya3
CC BY-SA 4.0
2023-05-25T21:01:21.170Z
That's the correct order the author put them in; if they wanted a different order, it's a bug in their program. The composition is `println ("Hello" (println ("World")))` where one `println` is (theoretically) dependent on the results of the other. I guess this is envisaging a concatenation of top-level applicative calls, rather than a single program?
Michael Homer
CC BY-SA 4.0
2023-05-25T21:05:09.943Z
@MichaelHomer That makes little sense to me; is the string literal `"Hello"` a unary operator? What does it do with its operand? Why doesn't `"World"` likewise need an operand?
kaya3
CC BY-SA 4.0
2023-05-25T21:10:18.820Z
*Every* term is a function from a stack to a stack, if you look at it that way (regardless of the order you write them in).
Michael Homer
CC BY-SA 4.0
2023-05-25T21:13:46.383Z
@MichaelHomer I guess I'm just not following what you mean by putting brackets into this program. In postfix order, `"Hello" println "World" println` would push a string to the stack, then pop and print it, then push another string, then pop and print it. If I had to put brackets to indicate which operands were consumed by which operators, I would write it like `("Hello") println ("World") println`, not like `((("Hello") println) "World") println`.
kaya3
CC BY-SA 4.0
2023-05-25T21:34:33.200Z
Yes, that's a reasonable way to think about those, though you can't in general do that: `3 4 swap 1 add` has add consume half a swap. The parentheses are not important if they're not helping, though, it was just an attempt to illustrate. I think I am not understanding the semantic model you're proposing in this answer.
Michael Homer
CC BY-SA 4.0
2023-05-25T22:04:09.720Z
@MichaelHomer The execution model for prefix notation is described [here](https://en.wikipedia.org/wiki/Polish_notation#Evaluation_algorithm) ─ I realised that my description was not exactly accurate so I edited my answer, but this doesn't change the order that side-effects would be evaluated in. If you have an example of a prefix-notation language where `print A print B` would print B before A, I would appreciate a link, since likewise I don't understand what the semantic model for that would be. (Unless it's just defined by reversing the tokens and evaluating like postfix.)
kaya3
CC BY-SA 4.0
2023-05-26T02:02:16.560Z
I think Om would do that, although I don't think it has a print operation; it does evaluate from the right. The question wasn't about Polish notation, though, other than in as far as Forth is in RPN if you squint at it. Functions with multiple outputs don't work well with actual Polish (i.e. tree-structured) notation, I think.
Michael Homer
CC BY-SA 4.0
2023-05-26T02:08:47.930Z
There is a trivial semantic model where programs are composed of unary functions from stacks to stacks: `mul 5 add swap 4 3` runs `mul` on the stack resulting from running `5` on the stack resulting from running `add` on the stack ... running `3` on an empty stack, which is also a working model for postfix notation, just composing in the opposite order. I believe that this is [the actual model of Joy](https://hypercubed.github.io/joy/html/j02maf.html), which is **the** concatenative language, so I don't think that it is so unusual (but Joy does use postfix notation for it).
Michael Homer
CC BY-SA 4.0
2023-05-26T09:25:22.553Z
@MichaelHomer By "unary operator" I mean one which pops one operand off the stack in order to be evaluated, as opposed to two operands, none, or some other number. Yes, you can also view it as all operators being functions which take in one stack and output one stack. Indeed this execution model is how concatenative languages normally work, but AFAIK concatenative languages normally use postfix ordering, since that's what follows naturally from "stack → stack" functions evaluated left to right. But the prefix model described in this answer also works like "stack → stack" functions, just ...
kaya3
CC BY-SA 4.0
2023-05-26T09:29:17.333Z
... the functions do different things. For example, in the postfix model, an instruction `23` takes a stack and simply returns a new stack with 23 added to the top of it; whereas in the prefix model, the stack might change more significantly if pushing 23 to the stack leaves enough operands for the top-most operator on the stack to be evaluated. So for example if the input stack for the instruction `23` is like `[add, 5]` then the output stack would be `[28]`.
kaya3
CC BY-SA 4.0
2023-05-26T10:05:45.660Z
I don't think we're going to resolve this, but to me, everything above the first line except the paragraph about Postscript has at best tangential relation to the question posed, which is meant to be about human ergonomics of ordering the composition operator-before instead of operator-after. There are other good semantic questions, I just didn't intend to ask them here, & on review I still don't *think* I did. Yes, concatenative languages do "*normally* use postfix ordering", and that's why I asked the question! The technical reasons that Forth uses that order are clear, but we don't have to.
Michael Homer
CC BY-SA 4.0
2023-05-26T10:11:24.080Z
@MichaelHomer The question says *"I can see no technical reason for these not to be equivalent, but there may be ergonomic reasons"* ─ I interpreted this as meaning that technical reasons would be relevant if there are any. I'm also not sure that the last part (about debugging) makes sense without reference to the implementation details. Anyway, I'm happy to accept an edit if you think parts of my answer aren't sufficiently relevant to the question.
kaya3
CC BY-SA 4.0
2023-05-26T21:08:28.897Z
I clearly failed to communicate in the question and I'm too close to it to see why. I intended it to be explicitly about reversing the tokens, explicitly not about alternative semantic models, explicitly note the orders were equivalent, and explicitly asking for human-factors answers, so I was surprised it got a response the first half of which is in essence "obviously you're not *actually* going to reverse the tokens, so here's why the semantic model is different...", but that is presumably because I didn't clearly express it when I said those things. I don't think I can edit it.
Michael Homer
<p>One ergonomic difference is for interactive REPLs.<br />
I'm focusing here on linear teletype-style REPLs.  I'll bring &quot;evidence&quot; from my REPL experience that is mostly <em>non-concatenative</em>, yet relevant to prefix vs. postfix.</p>
<p>It's very common in REPL usage to compute some values, see them, then feed them into more computation.  You don't know the later code you'll write until you see the intermediate values, so inputs &quot;must&quot; appear before function.</p>
<p>An entirely postfix language like FORTH, Factor etc. supports this workflow naturally - you <em>always</em> write code in data-flow order, so you can press Enter stop at any point, inspect the stack non-destructively, then write more logic using previous results.</p>
<pre><code>IN: scratchpad 3 4

--- Data stack:
3
4
IN: scratchpad +

--- Data stack:
7
IN: scratchpad 5 *

--- Data stack:
35
</code></pre>
<p>In prefix/infix languages like Python, the main workflows are:</p>
<ul>
<li><p>Assign intermediate results to a variable, later refer to it by name.</p>
<pre class="lang-ruby prettyprint-override"><code>&gt; sum = 3 + 4
=&gt; 7
&gt; area = 5 * sum
=&gt; 35
</code></pre>
<p>If omitted, many REPLs assign names implicitly, e.g. <code>_</code> in Python's &amp; Ruby's builtin repl, numbered <code>Out[7]</code> in Mathematica &amp; Jupyter etc.</p>
<pre class="lang-ruby prettyprint-override"><code>&gt; 3 + 4
=&gt; 7
&gt; 5 * _
=&gt; 35
</code></pre>
<p>Note how the resulting code has mixed order: data flows left &quot;in the small&quot;,  right/down &quot;in the large&quot;.  (almost all imperative languages do this! but still it's a conceptual complication.)</p>
</li>
<li><p>Re-run the whole command with extra logic added.<br />
Anecdotally, prepending code at start feels awkward!  Not sure why exactly but appending <code>| sort | uniq</code> at the end in shell, or some <code>.method_call</code> or  <code>|&gt; function</code> pipelining syntax feels better.<br />
I don't have any data why.  Is it merely an artifact of <kbd>Up</kbd> history recall leaving cursor at the end by default?  Is it because having stopped and <em>thought about</em> the new code significantly later it's natural to write &quot;in order of thinking&quot;?  Is it because the repeated portion of the command is less interesting, you want to see the new added part near the output?</p>
<pre class="lang-sh prettyprint-override"><code>$ expr 3 + 4
7
$ expr 3 + 4 | expr $(cat) \* 5   # bad example, expr doens't read stdin
35
$ expr 3 + 4 | jq '. * 5'
35
</code></pre>
</li>
</ul>
<hr />
<p>Counter-points, limiting the usefulness of linear-transcript REPL with postfix data-stack model:</p>
<ul>
<li>It's hard to push things on the stack in the order that will be most convenient to consume by later logic, <em>esp.</em> if you don't know that logic yet; you might need to reshuffle or put results into variables anyway, and to produce idiomatic code you'd later rewrite or factor into functions anyway.</li>
<li>Words consuming data off the stack are destructive — in the sense that if you later want to reuse lost results you need an ability to edit &amp; re-run code anyway, e.g. saving / DUP'ing some values in the middle.</li>
</ul>
<p>So I suspect environments making it easy to go back and edit are superior even for postfix?  (And once you have something like Jupyter or Light Table, it's equally easy to edit any part of the code &amp; re-evaluate, and other ergonomic considerations apply.)</p>
<hr />
<p>Prefix notation has a different interactive benefit — can help you discover available functions and their signatures before you code their arguments.<br />
By tooltips / tab completion, or by explicit help commands.</p>
<p>(In unix command-line, I'll frequently wastefully run <code>cmd1 | cmd2 | sort --help</code> just to read docs before completing the command.  Shell pipelines are only postfix wrt. stdin, but prefix wrt. flags, which interestingly feels like a sweet spot from this angle: I did build up input I want to sort before I start typing <code>| sort</code> but might not remember sort's flags.)</p>

CC BY-SA 4.0
2023-07-02T11:37:06.103Z
2023-07-02T11:37:06.103Z
Beni Cherniavsky-Paskin
CC BY-SA 4.0
2023-07-02T13:59:43.807Z
Welcome! On your points about pushing things in the right order to use later, or data being lost when you consume it, I think both are addressed by storing intermediate results in named variables.
kaya3
<p>This is probably a very subjective opinion, but your prefix notation doesn't look very readable compared to the postfix one.</p>
<p>The postfix notation has a clear &quot;imperative&quot; mental model: each word transforms some values on the top of the stack. So the example code <code>3 4 swap add 5 mul</code> can be mentally followed on the lines of</p>
<pre><code>3       [... 3]
4       [... 3 4]
swap    [... 4 3]
add     [... (4+3)]
5       [... (4+3) 5]
mul     [... ((4+3)*5)]
</code></pre>
<p>The prefix notation, <em>with a restriction that every word takes some fixed number of values and returns exactly one value</em>, is good ol' <a href="https://en.wikipedia.org/wiki/Polish_notation" rel="nofollow noreferrer">Polish notation</a>, which allows for a Lisp-like, or an expression-evaluator-like, mental model: <code>print mul 5 add 4 3</code> can be read as</p>
<pre><code>(print
  (mul
    5
    (add
      4
      3
    )
  )
)
</code></pre>
<p>I can't recall any language that uses this notation other than an esolang <a href="https://github.com/knight-lang/knight-lang" rel="nofollow noreferrer">Knight</a>, but (in my limited experience using it in code golf) I didn't have much problem writing and reading Knight code syntax-wise, so I guess it is ergonomic enough. (Knight allows subexpressions to be wrapped with parens <code>()</code>, which IMO does encourage this mental model.)</p>
<p>However, when you allow more arbitrary stack transformations, this mental model breaks down. Take the reverse of the program <code>3 4 swap 5 mul add</code>, which is <code>add mul 5 swap 4 3</code>. What are the arguments to <code>mul</code>? How about <code>add</code>? There is no easy way to track them, other than to return to the imperative model but reading words in reverse. Apparently people prefer to read code from left to right<sup>[citation needed]</sup>, so this switch of direction may incur a cognitive overhead on the programmers when reading code in this style. This also means people will tend to write programs from right to left, which doesn't go well with common text editors.</p>

CC BY-SA 4.0
2023-05-26T00:18:25.790Z
2023-05-26T00:18:25.790Z
Bubbler
CC BY-SA 4.0
2023-05-26T01:47:22.923Z
[Husk](https://github.com/barbuz/Husk) is a prefix concatenative language. It uses a higher-order function `flip :: (x -> y -> z) -> y -> x -> z` instead of `swap`. Of course, golfing languages are less focused on ergonomics.
alephalpha
# Should a concatenative language use prefix or postfix term ordering?
Posted by: username_0 on 2023-05-25
Concatenative languages compose subprograms (nonempty sequences of terms) by appending one to the other. Most of these languages use postfix notation, like in Forth:
3 4 swap add 5 mul

A few, like Om, use a prefix notation, where operators precede their arguments, though Om also has a novel semantics that I am not asking about here. We can imagine reversing the order of tokens in the program above:
mul 5 add swap 4 3

and interpreting them to produce exactly the same result, with operators now preceding the expressions producing their arguments. This prefix order is more analogous to most applicative functional languages, but the semantics of juxtaposition are different, indicating function composition instead of application.
In some ways, the postfix notation reflects the stack-mutation semantics of Forth, administered left-to-right, while a prefix notation more illustrates composition, but these are post-facto rationalisations.

Are there reasons to prefer one ordering to the other? I can see no technical reason for these not to be equivalent, but there may be ergonomic reasons. For example, is one more readily understood by the (non-)programmer, or more efficiently written? Does one somehow enable better library design? Will editing or debugging affordances be more available with one order? Or potentially other factors I haven't considered. There may not be a firm answer one way or the other, but I'd like evidence for when to use each order.
I would be particularly interested in results of any study examining this, if there is such a thing, but learned experience from developing or using such languages would also support an answer.
**Tags:** concatenative-languages language-ergonomics
---
## 3 answers
### Answer by username_1 on 2023-05-25. Score: 5
The natural implementations are different:

Postfix ordering requires a stack of only values, where operators are applied immediately, taking their operands off the stack. The execution loop for an interpreter is straightforward: read the next instruction from the program, and evaluate it.
Prefix ordering requires a stack which can contain both operators and values. An operator like add is pushed to the stack, and not evaluated until there are sufficiently many operands on the stack above it. The execution loop for an interpreter is different: read the next instruction from the program and push it to the stack; then while the top-most operator on the stack is followed by sufficiently many values for its operands, evaluate that operator.

This ignores how the implementation evaluates quotes, but that is covered in this other question.
It seems to me that the implementation is much simpler using postfix ordering, and this will be decisive for concatenative languages which aren't meant to be written by humans (e.g. PostScript).
There is also a semantic difference which favours postfix notation: in prefix notation, each operator must take a fixed number of operands, in order to determine when the operator should be evaluated. On the other hand, postfix notation allows an operator to accept a variable number of operands, e.g. by consuming the whole of the stack.

As discussed in the comments, either of these implementations could be used for either prefix or postfix order ─ you can just reverse the program's tokens to switch the ordering. However, this would give a language where the side-effects of instructions are evaluated in the opposite order to which those instructions are written. This seems undesirable to me, but in principle a language could be designed this way.
Alternatively, the language could be designed in such a way that instructions don't have side-effects, and instead a program's output is simply a value left on the stack when it terminates. Or for interactive programs, perhaps something like Haskell's IO monad could be used, so that the order that terms are evaluated in doesn't have to be the same as the order their side-effects are observed in.
So other implementations than the above two are possible, but I'll focus on these because they're straightforward, and have the desirable property that the program's side-effects are evaluated from left to right.

For concatenative languages meant to be written by humans, the ease of language implementation may no longer be the deciding factor.
The main ergonomic difference between these two approaches is what you already identified: the syntax places functions before their arguments, which is closer to how humans think about programming. A similar issue is that a variable name can precede its initialiser, which particularly matters when the initialiser is a long expression. Here's an example using my own toy concatenative language, fffff:
(
    n 3 % 0 = >three
    n 5 % 0 = >five
    ("fizz" print) three if
    ("buzz" print) five if
    (n print) three five or not if
    "" println
) >!print_num

This snippet declares a quote (i.e. a user-defined function) and binds it to the name print_num ─ but the name doesn't appear until after the end of the quote. This is a significant readability issue. With prefix notation instead, the name would appear at the start, which would be more sensible.
Another ergonomic issue is in debugging. If the program is paused during execution (e.g. due to a runtime error, or hitting a breakpoint), the programmer will be able to observe the current program state. As discussed above, prefix order and postfix order have natural implementations in which the program state would be a stack of operators and values, vs. a stack of just values, respectively. It's difficult to say which of these is more useful for debugging purposes, but a stack containing operators might be preferable since it more closely resembles a stack trace in an imperative or functional language, and may give better context about what the program was doing when it was paused.
> **Comments:**
> **username_0** (2023-05-25): I am intrigued by what you say about implementation differences: surely it's symmetric? The compiler can reverse the tokens to get either permutation for either input, so it *ought* to be able to choose implementation and surface order independently.  
> **username_1** (2023-05-25): @MichaelHomer It can reverse the tokens and execute that way, if you don't mind your program's side effects being executed in reverse order. `println "Hello" println "World"` in prefix notation would be reversed into a postfix program which prints "World Hello". I expect most programmers *would* mind this!  
> **username_0** (2023-05-25): That's the correct order the author put them in; if they wanted a different order, it's a bug in their program. The composition is `println ("Hello" (println ("World")))` where one `println` is (theoretically) dependent on the results of the other. I guess this is envisaging a concatenation of top-level applicative calls, rather than a single program?  
> **username_1** (2023-05-25): @MichaelHomer That makes little sense to me; is the string literal `"Hello"` a unary operator? What does it do with its operand? Why doesn't `"World"` likewise need an operand?  
> **username_0** (2023-05-25): *Every* term is a function from a stack to a stack, if you look at it that way (regardless of the order you write them in).  
> **username_1** (2023-05-25): @MichaelHomer I guess I'm just not following what you mean by putting brackets into this program. In postfix order, `"Hello" println "World" println` would push a string to the stack, then pop and print it, then push another string, then pop and print it. If I had to put brackets to indicate which operands were consumed by which operators, I would write it like `("Hello") println ("World") println`, not like `((("Hello") println) "World") println`.  
> **username_0** (2023-05-25): Yes, that's a reasonable way to think about those, though you can't in general do that: `3 4 swap 1 add` has add consume half a swap. The parentheses are not important if they're not helping, though, it was just an attempt to illustrate. I think I am not understanding the semantic model you're proposing in this answer.  
> **username_1** (2023-05-25): @MichaelHomer The execution model for prefix notation is described [here](https://en.wikipedia.org/wiki/Polish_notation#Evaluation_algorithm) ─ I realised that my description was not exactly accurate so I edited my answer, but this doesn't change the order that side-effects would be evaluated in. If you have an example of a prefix-notation language where `print A print B` would print B before A, I would appreciate a link, since likewise I don't understand what the semantic model for that would be. (Unless it's just defined by reversing the tokens and evaluating like postfix.)  
> **username_0** (2023-05-26): I think Om would do that, although I don't think it has a print operation; it does evaluate from the right. The question wasn't about Polish notation, though, other than in as far as Forth is in RPN if you squint at it. Functions with multiple outputs don't work well with actual Polish (i.e. tree-structured) notation, I think.  
> **username_0** (2023-05-26): There is a trivial semantic model where programs are composed of unary functions from stacks to stacks: `mul 5 add swap 4 3` runs `mul` on the stack resulting from running `5` on the stack resulting from running `add` on the stack ... running `3` on an empty stack, which is also a working model for postfix notation, just composing in the opposite order. I believe that this is [the actual model of Joy](https://hypercubed.github.io/joy/html/j02maf.html), which is **the** concatenative language, so I don't think that it is so unusual (but Joy does use postfix notation for it).  
> **username_1** (2023-05-26): @MichaelHomer By "unary operator" I mean one which pops one operand off the stack in order to be evaluated, as opposed to two operands, none, or some other number. Yes, you can also view it as all operators being functions which take in one stack and output one stack. Indeed this execution model is how concatenative languages normally work, but AFAIK concatenative languages normally use postfix ordering, since that's what follows naturally from "stack → stack" functions evaluated left to right. But the prefix model described in this answer also works like "stack → stack" functions, just ...  
> **username_1** (2023-05-26): ... the functions do different things. For example, in the postfix model, an instruction `23` takes a stack and simply returns a new stack with 23 added to the top of it; whereas in the prefix model, the stack might change more significantly if pushing 23 to the stack leaves enough operands for the top-most operator on the stack to be evaluated. So for example if the input stack for the instruction `23` is like `[add, 5]` then the output stack would be `[28]`.  
> **username_0** (2023-05-26): I don't think we're going to resolve this, but to me, everything above the first line except the paragraph about Postscript has at best tangential relation to the question posed, which is meant to be about human ergonomics of ordering the composition operator-before instead of operator-after. There are other good semantic questions, I just didn't intend to ask them here, & on review I still don't *think* I did. Yes, concatenative languages do "*normally* use postfix ordering", and that's why I asked the question! The technical reasons that Forth uses that order are clear, but we don't have to.  
> **username_1** (2023-05-26): @MichaelHomer The question says *"I can see no technical reason for these not to be equivalent, but there may be ergonomic reasons"* ─ I interpreted this as meaning that technical reasons would be relevant if there are any. I'm also not sure that the last part (about debugging) makes sense without reference to the implementation details. Anyway, I'm happy to accept an edit if you think parts of my answer aren't sufficiently relevant to the question.  
> **username_0** (2023-05-26): I clearly failed to communicate in the question and I'm too close to it to see why. I intended it to be explicitly about reversing the tokens, explicitly not about alternative semantic models, explicitly note the orders were equivalent, and explicitly asking for human-factors answers, so I was surprised it got a response the first half of which is in essence "obviously you're not *actually* going to reverse the tokens, so here's why the semantic model is different...", but that is presumably because I didn't clearly express it when I said those things. I don't think I can edit it.  
---
### Answer by username_2 on 2023-07-02. Score: 4
One ergonomic difference is for interactive REPLs.
I'm focusing here on linear teletype-style REPLs.  I'll bring "evidence" from my REPL experience that is mostly non-concatenative, yet relevant to prefix vs. postfix.
It's very common in REPL usage to compute some values, see them, then feed them into more computation.  You don't know the later code you'll write until you see the intermediate values, so inputs "must" appear before function.
An entirely postfix language like FORTH, Factor etc. supports this workflow naturally - you always write code in data-flow order, so you can press Enter stop at any point, inspect the stack non-destructively, then write more logic using previous results.
IN: scratchpad 3 4

--- Data stack:
3
4
IN: scratchpad +

--- Data stack:
7
IN: scratchpad 5 *

--- Data stack:
35

In prefix/infix languages like Python, the main workflows are:

Assign intermediate results to a variable, later refer to it by name.
> sum = 3 + 4
=> 7
> area = 5 * sum
=> 35

If omitted, many REPLs assign names implicitly, e.g. _ in Python's & Ruby's builtin repl, numbered Out[7] in Mathematica & Jupyter etc.
> 3 + 4
=> 7
> 5 * _
=> 35

Note how the resulting code has mixed order: data flows left "in the small",  right/down "in the large".  (almost all imperative languages do this! but still it's a conceptual complication.)

Re-run the whole command with extra logic added.
Anecdotally, prepending code at start feels awkward!  Not sure why exactly but appending | sort | uniq at the end in shell, or some .method_call or  |> function pipelining syntax feels better.
I don't have any data why.  Is it merely an artifact of Up history recall leaving cursor at the end by default?  Is it because having stopped and thought about the new code significantly later it's natural to write "in order of thinking"?  Is it because the repeated portion of the command is less interesting, you want to see the new added part near the output?
$ expr 3 + 4
7
$ expr 3 + 4 | expr $(cat) \* 5   # bad example, expr doens't read stdin
35
$ expr 3 + 4 | jq '. * 5'
35




Counter-points, limiting the usefulness of linear-transcript REPL with postfix data-stack model:

It's hard to push things on the stack in the order that will be most convenient to consume by later logic, esp. if you don't know that logic yet; you might need to reshuffle or put results into variables anyway, and to produce idiomatic code you'd later rewrite or factor into functions anyway.
Words consuming data off the stack are destructive — in the sense that if you later want to reuse lost results you need an ability to edit & re-run code anyway, e.g. saving / DUP'ing some values in the middle.

So I suspect environments making it easy to go back and edit are superior even for postfix?  (And once you have something like Jupyter or Light Table, it's equally easy to edit any part of the code & re-evaluate, and other ergonomic considerations apply.)

Prefix notation has a different interactive benefit — can help you discover available functions and their signatures before you code their arguments.
By tooltips / tab completion, or by explicit help commands.
(In unix command-line, I'll frequently wastefully run cmd1 | cmd2 | sort --help just to read docs before completing the command.  Shell pipelines are only postfix wrt. stdin, but prefix wrt. flags, which interestingly feels like a sweet spot from this angle: I did build up input I want to sort before I start typing | sort but might not remember sort's flags.)
> **Comments:**
> **username_1** (2023-07-02): Welcome! On your points about pushing things in the right order to use later, or data being lost when you consume it, I think both are addressed by storing intermediate results in named variables.  
---
### Answer by username_3 on 2023-05-26. Score: 4
This is probably a very subjective opinion, but your prefix notation doesn't look very readable compared to the postfix one.
The postfix notation has a clear "imperative" mental model: each word transforms some values on the top of the stack. So the example code 3 4 swap add 5 mul can be mentally followed on the lines of
3       [... 3]
4       [... 3 4]
swap    [... 4 3]
add     [... (4+3)]
5       [... (4+3) 5]
mul     [... ((4+3)*5)]

The prefix notation, with a restriction that every word takes some fixed number of values and returns exactly one value, is good ol' Polish notation, which allows for a Lisp-like, or an expression-evaluator-like, mental model: print mul 5 add 4 3 can be read as
(print
  (mul
    5
    (add
      4
      3
    )
  )
)

I can't recall any language that uses this notation other than an esolang Knight, but (in my limited experience using it in code golf) I didn't have much problem writing and reading Knight code syntax-wise, so I guess it is ergonomic enough. (Knight allows subexpressions to be wrapped with parens (), which IMO does encourage this mental model.)
However, when you allow more arbitrary stack transformations, this mental model breaks down. Take the reverse of the program 3 4 swap 5 mul add, which is add mul 5 swap 4 3. What are the arguments to mul? How about add? There is no easy way to track them, other than to return to the imperative model but reading words in reverse. Apparently people prefer to read code from left to right[citation needed], so this switch of direction may incur a cognitive overhead on the programmers when reading code in this style. This also means people will tend to write programs from right to left, which doesn't go well with common text editors.
> **Comments:**
> **username_4** (2023-05-26): [Husk](https://github.com/barbuz/Husk) is a prefix concatenative language. It uses a higher-order function `flip :: (x -> y -> z) -> y -> x -> z` instead of `swap`. Of course, golfing languages are less focused on ergonomics.  
---
