Hacker Newsnew | comments | show | ask | jobs | submit login

This isn’t concatenative except in the trivial sense of “stack-based”. Concatenative languages are functional languages with compositional semantics, which often happen to be most efficiently implemented as stack machines. Concatenative languages are interesting because they’re a combinator calculus like SKI[1] but with simpler semantics and useful algebraic properties.

Only allowing two-argument functions doesn’t cut it, and you need some means of returning multiple values as well. You also need a means of abstraction (e.g., Clojure fns) and combinators for application, abstraction, and stack manipulation. A full implementation of an interpreter for a concatenative DSL would be rather longer than this—though still probably in the realm of 100 lines.

[1]: http://en.wikipedia.org/wiki/SKI_combinator_calculus




Fogus linked to my project, Factjor:

https://github.com/brandonbloom/factjor

Factjor supports quotations, currying, composition, and has most of the primary combinators: dip, keep, cleave, spread, application, etc. It's only about 100 lines.

-----


> Concatenative languages are interesting because they’re a combinator calculus like SKI but with simpler semantics and useful algebraic properties.

It's difficult to have simpler semantics than SK calculus. Perhaps a more appropriate modifier in this instance would be "more convenient".

-----


Yes, that’s fair. The example I had in mind was to do with GC: I’m not sure you can implement an SK interpreter without it.

-----


I'm not sure that the presense of a stack is required for a concatenative language, but your point is well taken. Pesto5 is not enterprise ready.

-----


Right, that’s what I said. Just because it’s efficient to implement one language that way doesn’t mean it’s efficient to do that for every language in the same family. :)

With non-variadic arithmetic functions:

    (defn add [x]
      (cons (+ (first x) (second x)) (rest (rest x))))
Your “postfix” function can remain a simple “reduce”, but can be totally agnostic of function arity. That frees you up to write the basic combinators:

    (defn dup [x]
      (cons (first x) x))

    (defn zap [x]
      (rest x))

    (defn swap [x]
      (cons (second x) (cons (first x) (rest (rest x)))))

    (defn ap [x]
      (apply (first x) (rest x)))

    ...

-----


A data stack is indeed not required -- see Om (experimental):

http://concatenative.org/wiki/view/Om

It uses prefix notation: instead of a data stack, each function takes the remainder of the program for rewriting.

-----


I whether or not there is a stack is similar to the complementary nature of foldL vs parallel fold (ie Clojure's core/reduce vs reducers). Left-to-right concatenative languages make use of a stack and are appropriate for side effects and stream processing. However, there are pure concatenative languages that operate in parallel via term rewriting, which has a computational model akin to that of a DNA computer.

-----


Enchilada is a concatenative language which is not stack based but instead works through term rewriting.

-----


You seem to have missed the point of this fun little exercise. Search for "in no way indicative" and "debatable" in the OP.

-----


No no, I only said this for the benefit of others who might not be familiar with concatenative programming. The OP clearly knows what they’re doing.

-----


I, for one, appreciated the clarification.

-----




Guidelines | FAQ | Support | API | Lists | Bookmarklet | DMCA | Y Combinator | Apply | Contact

Search: