Systems vs. Exploration Languages
Languages are tools—albeit tools to which we become emotionally attached—and it's important to recognize the right tool for the job. This post identifies two broad categories of computer programming languages, Systems and Exploration, and lists some of the characteristics that distinguish them. Keep these in mind as you choose the technology for your next project.
Systems languages are fast and native. They allow unsafe operations and manual memory management, and guarantee deterministic destruction. They expose C ABIs so they can be called from other languages. Use a systems language when performance, static type safety, and direct access to hardware are important to you; for example, writing a device driver, low-latency trading system, or AAA video game. Rust, C, and C++ are archetypal systems languages.
Exploration languages are convenient and expressive. They have REPLs, garbage collectors, and dynamic type systems. They are interpreted, or compiled to portable byte-code. They guarantee memory safety. They have FFIs so they can call functions written in systems languages, wrapping those functions in idiomatic APIs. Choose an exploration language when developers need real-time feedback and the product must be flexible: Data science, ETL pipelines, and user interfaces are good examples. Python, R, and SQL are exploration languages.
Of course, plenty of languages fit somewhere between these extremes. Java and Go come to mind.
Most systems that survive the test of time seem to pair two languages, one from each camp. Unix, for example, is built from C as the systems language, and the shell as an exploration language. Web apps are effectively the combination of browsers written in C++ with UIs written in JavaScript. So, should you choose a Go-like language, or a combination of, say, Rust and JavaScript, or C++ and Python?
If you need something up and running ASAP, and neither a pure systems nor pure exploration language fits the bill, then choose a middle-of-the-road language like Go. If you want maximum performance, flexibility, and speed over the long run, then bite the bullet and accept a harmonious pairing of two languages into your heart. As of 2021, Rust and JavaScript seem like great choices for a wide variety of projects. (If Rust seems too hard, remember that you can prototype in JavaScript on Node.js. If JavaScript seems too messy, remember that you can move critical components into Rust, transpiled to JavaScript or compiled right to WebAssembly.)