The Standard Library#
Every language ships with a set of “batteries included” — ready-made types and functions so you don’t reinvent the basics. Julia’s is called the standard library, and a lovely fact about it is that it’s almost entirely written in Julia and open source (MIT licensed). You can read exactly how sort or Dict is implemented, and contribute improvements. This final chapter is a guided tour of what’s in the box.
Base: always there, no import needed#
Base is loaded automatically in every session. You’ve been using it the entire book:
Types —
Int,Float64,Bool,String,Char,Complex,Rational,Array,Tuple,NamedTuple,Dict,SetCore functions —
println,length,push!,sum,map,filter,sort,reduce,minimum,maximumMath —
sqrt,abs,exp,log,sin,round,floor,ceil,clampIntrospection —
typeof,eltype,fieldnames,methods,@which
A few Base functions worth knowing that beginners often miss:
reduce(+, [1,2,3,4]) # 10 — general fold
mapreduce(abs2, +, [1,2,3]) # 14 — map and reduce in one pass, no temporary
foldl(-, [1,2,3]) # -4 — explicitly left-associative
accumulate(+, [1,2,3,4]) # [1,3,6,10] — running totals
count(>(2), [1,2,3,4]) # 2
any(iseven, [1,3,5]) # false
all(>(0), [1,2,3]) # true
findfirst(>(2), [1,2,3,4]) # 3 — the index
zip([1,2,3], "abc") # pairs up two collections
partialsort([5,3,1,4], 1:2) # smallest two, without full sort
mapreduce deserves the callout. sum(abs2, xs) and mapreduce(abs2, +, xs) compute the sum of squares without ever materializing an array of squares. Many Base reductions take an optional function as their first argument this way — sum(f, xs), maximum(f, xs), count(f, xs) — and it’s consistently the allocation-free option.
Also note >(2) in those examples. That’s a partially applied operator: >(2) is a function that tests whether its argument is greater than 2. Very handy inside filter, count, and friends. (Julia 1.12 generalized this machinery with a Fix type, so more functions support partial application than before.)
Standard library packages#
These ship with Julia but need a using line. No installation, no Project.toml entry needed.
Statistics#
using Statistics
mean(xs)
median(xs)
std(xs)
var(xs)
quantile(xs, 0.95)
cor(xs, ys)
cov(xs, ys)
mean(A; dims = 1) # column means of a matrix
LinearAlgebra#
using LinearAlgebra
A \ b # solve Ax = b — the workhorse
det(A), tr(A), rank(A)
norm(v)
dot(u, v), cross(u, v)
eigen(A) # eigenvalues and eigenvectors
svd(A), qr(A), lu(A), cholesky(A)
I # the identity, sized automatically
Diagonal(v), Symmetric(A), UpperTriangular(A)
Those last few are worth understanding as a design lesson, not just an API. Symmetric(A) doesn’t copy anything — it wraps A in a type that tells the compiler the matrix is symmetric. Dispatch then picks specialized algorithms. Encoding a mathematical property in the type system, and getting a faster algorithm for free, is Julia’s whole approach in miniature.
Random#
using Random
rand() # uniform [0,1)
rand(1:6) # a die roll
rand(1:6, 100) # a hundred of them
randn(1000) # standard normal
shuffle([1,2,3,4])
Random.seed!(42) # reproducibility
rng = MersenneTwister(42) # or an explicit generator
Pass an explicit rng to functions in code you want reproducible. Relying on the global generator works until you add threads.
Dates#
using Dates
today()
now()
d = Date(2026, 7, 28)
d + Month(3) # 2026-10-28
Dates.format(d, "yyyy-mm-dd")
Date("2026-07-28", "yyyy-mm-dd")
dayofweek(d), month(d), year(d)
Real date arithmetic with calendar-aware periods. If you’ve done fiscal-period logic in another language you’ll appreciate that Month(1) knows February is short.
Test#
using Test
@testset "ledger" begin
@test net_pay(1000, 0.1) ≈ 900
@test_throws ArgumentError net_pay(-1, 0.1)
@test length(entries) == 3
end
Run with ] test. That’s the whole setup — no config file, no test runner to install.
Printf, Serialization, and friends#
using Printf
@printf("%.2f%%\n", 8.25) # C-style formatting
using Serialization
serialize("model.jls", my_object)
obj = deserialize("model.jls")
using Downloads
Downloads.download("https://example.com/data.csv", "data.csv")
Others in the box: Logging, Profile, SparseArrays, Distributed, Sockets, SHA, UUIDs, Base64, DelimitedFiles, Pkg itself.
SparseArrays#
Worth a special mention if you do any large-scale numerical work:
using SparseArrays
S = sparse([1, 2, 3], [1, 2, 3], [1.0, 2.0, 3.0])
S * dense_vector # dispatches to a sparse algorithm automatically
Again the pattern: a different type, the same operators, a completely different algorithm chosen for you.
Files and I/O#
# Read a whole file
content = read("ledger.csv", String)
lines = readlines("ledger.csv")
# Stream it — for files bigger than memory
open("big.csv") do io
for line in eachline(io)
process(line)
end
end
# Write
open("output.txt", "w") do io
println(io, "result: $value")
end
# Paths, portably
joinpath("data", "2026", "ledger.csv")
isfile(path), isdir(path), mkpath(dir)
basename(path), dirname(path), splitext(path)
Use joinpath rather than string concatenation with slashes. It’s the difference between code that works on your Mac and code that works on the deployment server.
How to explore further#
The standard library is large, so the most useful skill isn’t memorizing it — it’s knowing how to look things up:
?namein the REPL. Every function is documented. This is faster than a web search and always matches your installed version.apropos("interpolate")searches all docstrings for a word when you don’t know the function’s name.methods(f)shows every method of a function, with the file and line of each.@which f(x)tells you which one your call landed on;@edit f(x)opens it.names(Statistics)lists everything a module exports.The official manual is genuinely excellent as a reference.
A good habit: before writing a utility yourself, spend two minutes checking whether Base already has it. More often than you’d expect, it does — and the built-in version is faster, better-tested, and composes with everything else.
Where you are now, and where to go next#
Take a breath and look back at the ground we’ve covered. You started by installing Julia and printing “Hello, world!”. Along the way you learned:
how Julia stores data, and why the memory layout of a typed array is where the speed comes from,
control flow and functions, the everyday building blocks,
the collections you’ll actually use, and the broadcasting notation that makes working with them feel like mathematics,
how the type system is organized, and how to add your own types to it,
multiple dispatch — the idea the whole language is built around,
modules, environments, and how Julia makes reproducibility the default,
metaprogramming, and the discipline to use it sparingly,
how to borrow Python’s ecosystem and call into C when you need to,
who owns what data, and when it gets copied,
how to find and fix the handful of mistakes that separate slow Julia from fast Julia,
how to use every core in your machine, and your GPU,
and what the compiler is actually doing with all of it.
That’s a real foundation. You can now write Julia that’s expressive and fast — the exact combination that pulled me to this language in the first place.
From here, the natural next step is to point these skills at real problems. In future installments, that’s exactly where we’re headed: data analysis, visualization, transformation, and ultimately training and deploying machine-learning models — all the way from a research notebook to production hardware, in one language.
Thank you for coming this far with me. This book began as my own attempt to rebuild my research code on a foundation I could trust to scale, and if it’s helped you take even a few steps along that same path, then it’s done its job.
Now go build something.