Blurring Language Boundaries

Feb 13, 2023

The advice goes: pick the programming language that you already use or the one that makes sense for your domain. If you were doing anything in data, you would probably choose Python for libraries like pandas and numpy. If you were doing something with containers or Kubernetes, you might choose Go. If you were doing front-end development, you'd surely choose JavaScript or TypeScript.

You even had languages like C# and .NET that were specially made for a particular environment (vs. Java).

But the language boundaries are blurring quickly.

Intermediate languages – This idea has been around forever, and the most famous implementation is probably the Common Intermediate Language Runtime (CIL) that targets the Common Language Runtime (CLR) for .NET. You had languages like C#, F#, IronRuby, IronPython that compiled down to the CIL and were runnable via the CLR.

The evolution of this is WebAssembly (Wasm) which is a compilation target for LLVM-based languages.

Embedded runtimes –  Instead of compiling your programs to common formats, you could simply embed a language runtime in another language. It might mean a python interpreter in Rust (RustPython), or JavaScript in Go (via v8 bindings).

Cross-language Function Calls – Intermediate languages often have another benefit beyond common runtime infrastructure – there is usually a way to do cross-language calls. That might mean calling a JavaScript function from Go via Wasm, or vice versa. Some languages also have the ability to call C or C++ code (e.g., Go, Rust, Zig).

Generated code – There are more libraries that will automatically scaffold client/server stubs for multiple languages – see OpenAPI or protoc.

Transpilation – A final emerging one is source-to-source compilation. Translating one language to another. This is sometimes a lossy translation – what does it mean to translate a Python class to a Go struct? In the past, this was painstakingly done by hand (albeit a great way to practice your programming). Now, the latest LLMs are pretty good at keeping semantic meaning and transpiling code (better than most humans I'm sure). For many libraries, we might see polyglot representations via LLMs.

While the trend has generally been fewer languages over the years, maybe we'll go back to having a widespread number of languages that all can interact with each other. Or, maybe we'll just have one meta-language that can call everything.