
A Simply Arited Concatenative Language - jamesbowman
https://suhr.github.io/obsc/
======
etatoby
> _In our notation, it 's just drop dup (^2) + (^2) - abs. Simple, readable,
> beautiful._

Considering how the author is not presenting a language for stack
manipulation, but for defining functions of fixed arity, I fail to see how
that style is supposed to be simpler or more readable than the usual
formulation, in the syntax of your choice, for example: fun x y z -> x^2 + y^2
- abs y

> _programming is finally liberated from von-Neumann style_

No, it's not.

Not until you show me how a sorting algorithm (say) written in that FP/FL
(J?)-inspired style is just as readable, but with less potential bugs.

Also, not until you show me how a complex algorithm written in that style can
be more easily synthesized to a FPGA or some other non-von Neumann computing
platform.

I will agree that ';' is a nice idea, but extraordinary claims require
extraordinary evidence.

In particular, the article fails to explain what device is supposed to replace
recursion or unbounded iteration, that allow Turing-completeness (and modern
software as a consequence) to exist in the first place.

~~~
enz
The article does not seem to emphasis on that, but in a concatenative language
you have "combinators" to achieve looping, recursions, etc. For example, the
Joy language has combinator for "applying a function" until a certain
condition holds, etc. Also, you have the classics: `map`, `fold`, `filter`, so
certain constructions just look like Haskell point-free style.

It seems a bit crazy but you can have a pretty readable program by defining
many litle functions with an explicit name.

------
zokier
I feel like the syntax could do with bit more explanation. For example in "(*
) + (* )" the use of parenthesis is not explained anywhere as far as I can
tell. Also, shouldn't it be "(* ) `+` (* )" instead if "+" is used as an infix
function instead of postfix, i.e. so that the expression desugars into "(* ) ;
(* ) +"

~~~
tmerr
This is likely borrowed from Haskell where functions starting with special
characters are treated as infix. Parens and backticks allow for switching
between the conventions

    
    
        add a b = a + b
        -- these are all the same
        3 + 4
        (+) 3 4
        add 3 4
        3 `add` 4
    

The article might also make slightly more sense in context, I think it was in
part an idea for how to make infix notation more useful in Kitten:
[https://github.com/evincarofautumn/kitten/issues/174](https://github.com/evincarofautumn/kitten/issues/174)

~~~
ghusbands
To some extent, yes, but the article silently switches the meaning of + about
halfway through. That's why there's confusion.

------
tom_mellior
Since nobody else seems to care, I'll just put this out here: "arited" is
really rather weird. I would say "aritied" instead (pronounced "ari-teed", not
"ari-tied").

Does anyone know of a parallel construction turning any word ending in "-ity"
into a past participle?

~~~
dgreensp
I would write “aritied.” The article also uses the word “simpliest,” and there
are a few other language oddities.

~~~
evincarofautumn
Yeah, and their name on Github is in Russian (sorta like “toasty”, as in a
small toast) so they’re probably just not a native English speaker. I would
also write “aritied”, and that’s what I’ve been saying when talking about this
article.

Speaking of “simpliest” though, even as a native speaker I sometimes use
“-lier” and “-liest”, but rather to form comparative & superlative adverbs,
e.g. “He solved it quicklier than I did”.

------
Mathnerd314
Author's implementation in rust:
[https://github.com/suhr/esobsc](https://github.com/suhr/esobsc)

The parser and AST have tests, which clear up some of the syntax confusion,
but it doesn't have the function definitions used in the last code example.

~~~
glibgil
More details in this lengthy commit message
[https://github.com/suhr/esobsc/commit/809241a726f2c97dac90bc...](https://github.com/suhr/esobsc/commit/809241a726f2c97dac90bccf2779b3792c6bc5bf)

------
ghusbands
The main invention here is being able to write a function as drop dup (^2) +
(^2) - abs, meaning the same as fn(x,y,z)=>( x * x + y * y - abs(y)).

But, it does not read at all naturally for a concatenative language. The first
two atoms (drop, dup) work in the usual fashion (directly and immediately
affecting the stack). Then, the (^2) is just a syntactic input for the + after
it, which is now an infix operator, also consuming the (^2) after it. But
these _still_ don't yet affect the stack, as the - is also consuming atoms and
it consumes the final abs. Then, the expression so built is run against the
current stack. It gives the impression of elegance and flexibility by throwing
away the very thing that makes concatenative languages what they are.

There are better solutions, like using a scratch space (like the return stack,
given in another comment) or otherwise explicitly making given atoms input or
output from/to a non-default location.

------
astrobe_
<rant>

The "why concatenative programming matters" example is a strawman to begin
with. The correct solution in standard Forth is "DUP >R DUP * SWAP * + R> ABS
-" not the rot3 garbage they exhibit (yes, I ignored the useless z parameter
because it's beyond the idiocy I can deal with).

Same goes for the (ab+cd) example, that simply writes "* >R * R> +".

Two stacks, problem solved. Forth lets you use the return stack for a reason.
If you're a chicken, just provide a second user stack and hide the return
stack. Problem solved.

But I guess that introducing and writing about the _powerful_ (this word,
really, should be treated as an intellectual smell) ";" operator is more fun.
The only problem is that this operator actually doesn't work on stacks but
arrays. Oops.

But, hey, can have infix notation!

</rant>

~~~
Someone
> The correct solution in standard Forth is "DUP >R DUP * SWAP * + R> ABS -"

I don’t think that can be correct. Multiplication is commutative, so SWAP
before * doesn’t do anything, getting “DUP >R DUP * * + R> ABS -“, which means
it computes x^2 y for some x and y somewhere along the way.

To compute y^2+x^2-|y| in forth, I would use multiple functions, for example

    
    
      : ^2 DUP * ;
      : x^2-|x| DUP ^2 SWAP ABS - ;
      : f x^2-|x| SWAP ^2 + ;

~~~
astrobe_
I stand corrected, I forgot a DUP:

    
    
        DUP >R DUP * SWAP DUP * + R> ABS -
    

I didn't want to use helper words to allow for a 1:1 comparison.

And I also forgot that standard Forth has TUCK (<=> SWAP OVER), so one can do
it without the return stack as well (using helpers this time):

    
    
        TUCK ^2 SWAP ^2 + SWAP ABS -

------
drallison
Posted 20 days or so ago but did not find many upvotes. My comments on the
original post are still relevant:

\-----

1 point by drallison 20 days ago [-]

Interesting but incomplete paper, apparently cited in from Redit although
located on github.

Sadly, there is no information about who the author might be. One of the redit
comments suggests that the author is gopher9.

The paper does cite as examples several of James Purdy's lanugage experiments.
He is evincarofactum@github.

~~~
evincarofautumn
As an aside, my name is Jon Purdy, and my username is “evincar of _autumn_ ”
(here, GitHub, gmail, most places).

~~~
drallison
Sorry Jon, a slip of the keyboarding synapse. Anyone interested in language
design should look into Jon's experiments with concatenative languages.

------
xelxebar
I only recently found out about J and had never heard about APL before. Is the
dc (predecessor of the bc cli calculator) syntax in the same family here?

------
Chiba-City
This is lovely. Its treatment of arity reads like an implicit pattern matching
against tuples across the operators.

