# Why Julia

"Pick one: a language that's easy to write, or a language that's fast."

For most of my career that was simply the deal, and everyone I worked with accepted it. You prototype your model in a comfortable, high-level language, you get it working, you prove the idea — and then somebody rewrites the whole thing in C++ so it can actually run in production. Two codebases. Two skill sets. Two sets of bugs. And a translation step in the middle where your careful research quietly turns into something slightly different.

The Julia community has a name for this: the **two-language problem**. Julia exists to make it go away.

I want to be careful here, because language arguments are boring and I'm not interested in having one. I love Python. I use it every day. It is not "slow" — badly written code is slow, and you can write badly performing code in any language on earth. Julia will not fix your algorithms. What Julia *does* fix is the specific, structural situation where the language itself stands between you and the machine, and your only escape hatch is to leave the language.

## The problem I actually had

I train neural networks for finance and supply chain analysis. During the COVID-19 pandemic I built models that anticipated supply chain shortages, and they worked — in a notebook, on a sample of the data. Moving them to production was a different story. The parts that mattered had to be rewritten, optimized, and parallelized by people who weren't me, using tools that weren't mine, and by the time that pipeline finished, the crisis had moved on.

That experience is what sent me looking. Julia was the first language where the answer to "how do I make this fast?" was not "rewrite it somewhere else" but "add a type annotation and look at what the compiler did."

## What Julia actually is

Julia is a high-level, dynamically-typed language that is **compiled**, not interpreted. Every time you call a function, Julia looks at the concrete types of the arguments you passed, compiles a specialized machine-code version of that function for exactly those types, and caches it. The next call with the same types runs native code.

That single design decision is where the speed comes from, and it explains almost everything else about the language:

- **You write code that looks like math**, because you're not manually managing memory layouts to get performance.
- **Types are optional but meaningful.** You can leave them off and the compiler will usually infer them. When you write them down, you're helping the compiler, not appeasing it.
- **Multiple dispatch is the core paradigm.** Which method runs is decided by the types of *all* the arguments, not just the first one. This sounds like a small technical detail. It is the single most important idea in the language, and we'll spend a whole chapter on it.
- **The standard library is written in Julia.** When you want to know how `sort` works, you read Julia source, not C. And when you think you can do better, you can.

## The honest trade-offs

I'd rather tell you the rough edges up front than have you discover them at 2 a.m.

**Latency.** Because Julia compiles on demand, the first call to a function is slower than subsequent ones — the famous "time to first plot." This was genuinely painful in the early days. It has improved enormously (native code caching landed in 1.9 and every release since has chipped away at it), but it's still a thing you'll notice, and you should know why it happens rather than being surprised by it.

**A smaller ecosystem.** Python has a package for everything. Julia does not, yet. The scientific and numerical corners are excellent and in some cases best-in-class. The web-app and business-tooling corners are thinner. We'll cover calling Python directly from Julia so this is rarely a blocker, but be realistic about it.

**Fewer people to ask.** Julia sits around #30 in the popularity rankings. The community is unusually helpful and unusually expert, but it is small.

None of these bothered me enough to outweigh the thing I came for. Your calculation might be different, and that's fine.

:::{note} Where Julia stands today
Julia hit `1.0` in 2018 and has kept a strict backwards-compatibility promise ever since — code written for 1.0 still runs today. The current stable line is **1.12**, with **1.10** as the long-term support (LTS) release, and 1.13 in release-candidate testing as I write this.

The last few releases have been quietly significant: multithreaded garbage collection, native code caching that slashed startup latency, a `public` keyword for marking API surface, and — the one I find most exciting for my own deployment problem — an experimental `--trim` mode in 1.12 that strips unreachable code from compiled binaries. In the Julia team's own testing that took an executable from 206 MB down to 1.6 MB. A Julia program you can actually ship as a small binary is a real change in what this language is for.
:::

That's the pitch, and it's the last time in this book I'll talk about Julia in the abstract. Let's install it.
