18 comments

[ 3.6 ms ] story [ 51.8 ms ] thread
Hi, this is my personal programming language project, Mlatu.

Mlatu is a statically typed concatenative programming language. It is purely functional with algebraic effects. It currently compiles to Rust but I may switch to Erlang.

I’d love any feedback or constructive criticism you guys have!

Good on ya for scratching an itch!

> "It currently compiles to Rust but I may switch to Erlang."

Why one or the other? Why not both? :)

Thanks. To answer your question, the current Rust codegen is pretty terrible performance wise, and all stack manipulations happen to a global mutable Vec. I’m hoping by switching to Erlang, I can take advantage of some of its list and pattern matching optimization, as well as TCO. It would also mean a new focus for the language, as I could add concurrency features as a goal rather easily.
This sound weird. Erlang is "slower" than Rust, like a lot and specially in this kind of stuff.
It’s not that Erlang is faster than Rust, but that the way I would translate Mlatu to Erlang would be more natural and Erlang-like than the current translation to Rust is, which would probably entail performance improvements.
I understand that clashing semantics could lead to this, but also think maybe you need a different data structure/patter on Rust? Anyway if you also will leverage more stuff from the Erlang ecosystem is certainly the way to go.
I was/am using a `Vec<Rep>` where `Rep` is an enum containing the different primitive types of Mlatu, which worked fine semantically but was just very slow for the amount of pushing and popping off I had to do. Thanks for your response, I do think I want to leverage more stuff from the Erlang.
Could this be invoked directly from the bash CLI as a sort of fully featured pipe based syntax layer? Curious for your thoughts here
I’m not really sure what you’re saying here, but that’s probably on me. Are you saying executing Mlatu scripts from its CLI?
Awesome to see. Has always thought there were too few concat langs out there. And also really nice that you connect it really well it seems to func prog.

I've even felt this niche so underrepresented that I have been thinking about creating a language for it myself. So maybe you beat me to it, or rather I can look to you for some inspiration :p

Question: What made you chose to compile to Rust instead of to LLVM or something like that? Do you make use of the memory safety you gain this way in some interesting ways?

Thanks. I would like to see more concatenative pauses as well, so don’t be discouraged from creating your own.

To be honest, I chose Rust because it was the most performant imperative language I know, not so much for its memory safety. I chose to transpile instead of generating LLVM because I wanted to focus on the frontend and type system more than the backend, and LLVM felt like it would get in the way more than enable it.

coi lo finti .i ki'e .i pe'u ko se purdi lo bangu
Are all stack-based languages concatenative? What would it take for a stack language to not be concatenative?
Nornally, we call a language concatenative if the concatenation (writing one after the other) of two programs p and q represents the program that computes the composite of the functions that p and q compute.

This definition is far from rigorous, but it's good enough for identifying concatenative languages in practice.

Most concatenative languages are stack-based, but there are some stack-based languages that are not concatenative (e.g. Befunge, a 2d language with self modifying code) and concatenaive languages that are not stack-based (e.g. Enchilada, which is based on term rewriting).

By your definition, even Python is concatenative, as is any language whose “main” is implicit and allows shadowing.

The definition I saw ages ago is much more strict:

If P is a program in a concatenative language, then for any A, B such that P=concat(A,B) and A and B are non empty valid programs, then executing A followed by executing B is equivalent to executing P.

This does classify Forth, Joy and Factor as concatenative but not Python or line-number-less Basic. Not familiar with Enchilada.

I actually got interested in this from a data compression persepective - dictionary compression of a concatenative program - even something as simple as LZ78, is LZ optimal, but still executable without decompressing…..

> By your definition, even Python is concatenative, as is any language whose “main” is implicit and allows shadowing.

Not that it's worth arguing over a definition that's specifically marked as non-rigorous, but your statement is wrong, and Python is not concatenative under the definition presented above.

The definition is fairly clear: a language is concatenative if the concatenation of two programs p and q represents the program that computes the composite of the functions that p and q compute. We can turn this into a formal definition: if we let concat(-,-)denote concatenation, o denote function composition, and [x] denote the function that the program x represents, the requirement is that the equation

[concat(p,q)] = [q] o [p]

should hold for all programs p,q.

One would struggle to define the meaning of [-] for Python programs, much less prove that the equation above holds for some reasonable definition of the brackets [-]. (And if you could, then Python would be considered concatenative under your definition too)

I am talking about simple string concatenation. Take two python programs "a.py" and "b.py", exclude command line arguments and stdio file descriptors - and, yes, the string concatenation of "a.py" and "b.py" will generally execute the same computation / "function" that executing "a.py", followed by executing "b.py" will compute.

That's true of Forth as well (and you don't even need to exclude the stack state), but not of C.

And indeed, it's not worth arguing about a non-rigorous definition, except that at the surface level there's a very inherent difference between the definition you presented and the one I know - which goes to the (rather unusual) definition of "concatenation" which appears to require function application in your definition, unlike the common use of the term in software in general.

A quick look at Wikipedia[0] indicates we are both right; The overall definition does refer to programs as functions, but the "Properties" part says "Any subexpression can be replaced with a name that represents the same subexpression. This is referred to in the concatenative community as factoring and is used extensively to simplify programs into smaller parts." It is likely an equivalent requirement (from what I remember, it is, but I don't remember all the details), but relies on the standardized, general meaning of "concatenate" rather than a narrow one specifically for this definition.

[0] https://en.wikipedia.org/wiki/Concatenative_programming_lang...