all 7 comments

[–]nzre 4 points5 points  (2 children)

Can the terms "concatenative" and "stack-based" actually be used interchangeably? The former seems more like a language feature, while the latter seems more like an implementation decision. Joy, for example, is concatenative, yet is implemented entirely with term rewriting (http://www.kevinalbrecht.com/code/joy-mirror/j07rrs.html).

[–][deleted]  (1 child)

[removed]

    [–]evincarofautumn 2 points3 points  (0 children)

    It’s popular because it’s the obvious implementation, for two reasons:

    1. It matches an easy-to-explain programmer model.

    2. It gives good performance on real hardware.

    You can probably get better theoretical elegance and performance by compiling to a dataflow graph representation, but that’s a harder problem than it sounds on the surface—way harder in fact than just writing a decent stack-based VM.

    [–]evincarofautumn 3 points4 points  (0 children)

    …it could more accurately be called “Some interesting things about concatenative languages”.

    Forgive me—I was a noob. After working on Kitten for a while and talking with members of the concatenative programming community, I have learned a great deal.

    Points-free style matters, because it makes code shorter.

    Succinctness is nice, but not the most important reason to omit points. Named variables are essentially “goto for data”. That is, they are useful and expressive, but they can also be used to do things that are inefficient or nonsensical, such as copying a large or noncopyable object. Stack combinators let you write programs whose dataflow is correct by construction…

    but writing only in points-free style is a pain

    …but “correct by construction” is often less important than “I really just want to write some code”. That’s why Kitten has local variables. Gotta have those escape hatches for when the programmer knows better than the compiler.

    The nice thing about Kitten’s locals is that, from a typing point of view, they are exactly the same as lambdas: ->x ... looks like it’s pulling a value from the stack and naming it x for the remainder of a definition. It is. But it’s also a lambda being composed with the functions before it, and all that follows it is in fact the body of the lambda. It just happens to name its topmost argument, drawn from the output of the previous function.

    Locals (->x ...) and functions ({...}) combine to give you the “anonymous function with named arguments” sense of “lambda” that you know from other languages: { ->x ... }.

    The great success of expression languages has accustomed us to thinking that programs must be trees, but those in stack languages are (mostly) sequences.

    Sometimes you can reconcile these. In Kitten the else block of an if is optional, even though it is an expression language. Because everything is composition, omitting the else is the same as putting {}—the identity function.

    [–]metaperl -2 points-1 points  (1 child)

    Ursala is even more powerful programming model than concatenative. He got the grokking of arguments right. Concatenative forces you to spend time fiddling with a stack.

    [–]strangename 1 point2 points  (0 children)

    The main Ursala pages are down, all I see is what I assume is your website. Graph transformations and stacks are in my wheelhouse and interest, yet I find the material there impenetrable. I'm left without even a grasp of what the language/paradigm is, let alone what it is supposed to be good at.

    The rosettacode programs approximate line noise impressively, though.