Skip to content(if available)orjump to list(if available)

From Languages to Language Sets

From Languages to Language Sets

8 comments

·March 14, 2025

emidln

This is one of the reasons I like Clojure. There are very useful dialects with broad overlap between:

Browser / JavaScript environments -> ClojureScript

General Purpose (JVM) -> Clojure

Fast Scripting -> Babashka (although I've used ClojureScript for this in the past)

C/C++ Interop -> Jank (new, but progressing rapidly and already useful)

I can largely write the same expressive code in each environment, playing to the platform strengths as needed. I can combine these languages inside the same project, and have libraries that have unified APIs across implementation. I can generally print and read EDN across implementations, provided I register the right tag handlers for custom types (this is one area jank still has to catch up). Reader conditionals allow implementation-specific code as needed.

I'm really excited about Jank giving me a good alternative to JNI/JNA/Panama when I need my Clojure to touch OS parts the JVM hasn't wrapped.

andyferris

One thing I'll note is we tend to use languages from different levels in different settings (front end, back end, systems) and we spend an awful lot of time writing glue code to get them to talk to each other.

A major advantage of the proposed approach is automated FFI and serialization/deserialization between languages in the same language set. RustScript would be able to accept a struct or enum from Rust or RustGC, and vice-versa. You could have a channel with different languages on either end.

You can also see that we _want_ something like this, e.g. we bolt TypeScript on top of JavaScript, and types onto Python. If JavaScript (or python) were designed so they could be more easily compiled (notably, no monkey patching) then they would support level 2 as well.

I have been thinking of level 2 or 1 languages that support the higher levels. This is a really good framing. (The problem with going the other way is the implementation decisions in the interpretter often constrain how the compiler can work, e.g. CPython is dominant because all the libraries that make use of the CPython FFI, and similarly for NodeJS. It is easier to interpret a constrained language than to compile a dynamic language designed with an interpretter in mind).

sitkack

Back when I did some high perf Python, I’d define my data at C structs and bump allocate those structs in a list using the cffi.

It is not unlike defining your data model for SQL so that you can have sane data access.

munificent

> One language could combine the 2nd and 3rd level though. A language that can be interpreted during development for fast iteration cycle, but compiled for better performance for deployment. There isn’t such a language popular today though.

I'm not sure if Dart counts as "popular", but it otherwise fits this bill. It has a JIT and can startup pretty quickly and interpret on the fly. You can also hot reload code changes while a program is running. And it can ahead-of-time compile to efficient machine code when you're ready to ship.

rickcarlino

This is a better taxonomy of what a language is rather than the dated concept of “High-level” vs. “Low-level”.

null

[deleted]

teaearlgraycold

I’m a strong supporter of adding an automatic GC to Rust. Although it seems difficult to justify as RustGC code wouldn’t be trivial to convert to traditional Rust. But going in the opposite direction should be trivial.