Julia — Reference
Source: https://docs.julialang.org/en/v1/
Julia
- Created: development began 2009; first public release 2012-02-14 by Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and Alan Edelman (Wikipedia).
- Latest stable: Julia 1.12.6 (docs as of 2026-04-09) (docs.julialang.org).
- v1.0: 2018-08-08 (the “no-breaking-changes” promise begins).
- Owner: JuliaLang open-source project; commercial steward JuliaHub, Inc. (formerly Julia Computing, founded 2015). License: MIT.
- Paradigms: multi-paradigm; multiple dispatch is the central organizing principle; functional, imperative, and (informal) OO supported.
- Typing: dynamic, strong, optional type annotations; rich parametric type system; types are first-class runtime values.
- Memory: tracing, generational, parallel garbage collector (Julia 1.10+).
- Compilation: JIT via LLVM; method specialization on argument types; AOT possible via PackageCompiler.jl (sysimages, app bundles).
- Primary domains: scientific computing, numerical analysis, ML, differential equations, climate, finance, pharmacometrics, HPC.
- Official docs: https://docs.julialang.org/en/v1/
At a glance
Julia attacks the “two-language problem”: prototype in a high-level language, ship in C++. It is dynamically typed but specialization-compiled per argument signature, so well-written Julia is within 2x of C for tight loops while feeling like Python or MATLAB. Multiple dispatch is everywhere — +, print, and your own functions all dispatch on the types of all arguments, enabling composability that single-dispatch OO cannot match (DifferentialEquations.jl + Measurements.jl + Unitful.jl just compose).
Getting started
Install: juliaup is the official installer/version manager (since 2022). curl -fsSL https://install.julialang.org | sh (Unix), winget install julia -s msstore (Windows). Manage with juliaup add 1.10, juliaup default lts.
Hello world:
println("Hello, world!")Run: julia hello.jl or paste into the REPL.
REPL: launch with julia. Has four modes accessed via prefix keys:
julia>default?help mode (?map);shell mode (;ls)]package mode (]add Plots)
Project layout (a package):
MyPkg/
Project.toml # name, uuid, deps, compat
Manifest.toml # exact resolved versions (lockfile)
src/MyPkg.jl # module entry point
test/runtests.jl
docs/ # Documenter.jl source
Package/build tool: built-in Pkg (using Pkg; Pkg.add("Plots") or ]add Plots). Pkg manages environments per directory via Project.toml + Manifest.toml (lockfile). Activate with ]activate .. The General registry (https://github.com/JuliaRegistries/General) hosts ~10,000+ packages.
Basics
Types and literals:
Int(platform-sized, usuallyInt64),Int8/16/32/64/128,UInt*,Float16/32/64,BigInt,BigFloat,Bool,Char(Unicode codepoint),String(UTF-8),Symbol(interned,:foo),Rational(3//4),Complex(1 + 2im).- Containers:
Vector{T}(=Array{T,1}),Matrix{T}(=Array{T,2}),Tuple,NamedTuple((a=1, b=2)),Dict{K,V},Set{T}. nothing(singleton,Nothingtype),missing(statistical missing,Missingtype),Union{T, Nothing}is the optional pattern.
Variables/scoping: dynamic typing with optional :: annotations. Lexical scoping; local, global, const modifiers. Top-level scope of a module is global; let introduces a new scope.
Control flow: if/elseif/else/end, for x in xs ... end, while ... end, break, continue. Ternary: cond ? a : b. Short-circuit: cond && action, cond || fallback. Comprehensions: [x^2 for x in 1:10 if isodd(x)]. Generators: (x^2 for x in 1:10).
Functions:
add(x, y) = x + y # short form
function add(x::Int, y::Int) # method on Int,Int — multiple dispatch
x + y
end
add(x, y; verbose=false) = ... # keyword args after ;
sq = x -> x^2 # anonymous
map(x -> x^2, 1:5)Last expression is the return value; return is optional but allowed for early exit. Methods are added to generic functions — every function has potentially many methods.
Strings: UTF-8 native, immutable. Indexing is by byte offset, not character: s[1], but iteration for c in s is by character. string("a", 1, :b) for concat, * also concatenates strings ("a" * "b"). Interpolation: "x = $(x+1)". Raw strings: raw"C:\path". Triple-quoted multi-line: """...""".
Collections: 1-indexed by convention (column-major arrays, like Fortran/MATLAB). push!, pop!, append! (the ! suffix marks mutation). Broadcasting with .: sin.(xs), xs .+ ys, f.(a, b) — fuses into a single loop with no temporaries.
Intermediate
Type system depth:
- Abstract types (
abstract type Number end) form a tree; concrete types are leaves and only they can have instances. - Parametric types:
Vector{T}whereT <: Number. Type parameters are inferred or explicit. Union{Int, String},Tuple{Int, String}(covariant in tuples),Type{T}(the type representingT).whereclauses constrain method signatures:f(x::Vector{T}) where T <: Number.- Triangular dispatch:
f(x::T, y::T) where Trequires both args same type.
Modules: module MyMod ... end. using (brings names into scope), import (bring in qualified). Submodules via nesting. Each package is a top-level module. Re-export with export.
Error handling: throw(ErrorException("msg")), error("msg"). try ... catch e ... finally ... end. Exception types form a hierarchy under Exception. @assert cond "msg" for invariants. Idiomatic: return nothing or Union{T, Nothing} for absence rather than throwing.
Concurrency primitives:
- Tasks (coroutines):
t = @task f(); schedule(t),fetch(t).@async expr.Channel{T}for CSP-style. - Threads (true OS threads, set with
julia -t autoorJULIA_NUM_THREADS):Threads.@threads for i in ...,Threads.@spawn. Atomics viaThreads.Atomic{T}.ReentrantLock,SpinLock. - Distributed (multi-process):
using Distributed; addprocs(4); @distributed for ...; pmap(f, xs). Per-process workers communicate by message passing.
I/O: read, write, open(f, "r") do io ... end. Printf.@printf, @sprintf. Streams: stdin, stdout, stderr. IOBuffer for in-memory. JSON via JSON.jl / JSON3.jl. CSV via CSV.jl + DataFrames.jl.
Stdlib highlights: LinearAlgebra (BLAS/LAPACK wrappers, \, eigen, svd), Statistics (mean, var, cor), Random (RNGs), Dates, Printf, Test (@test, @testset), Distributed, Serialization, Sockets, Logging, Pkg, REPL, Markdown, Profile, SharedArrays.
Advanced
Memory / GC: tracing, generational mark-sweep with parallel marking (since 1.10) and parallel sweep (since 1.11). Manual control via GC.gc(), GC.enable(false). Allocations are the #1 perf killer — @allocated, @time, and the --track-allocation=user flag identify hot spots. Stack-allocate small immutables by making them struct (immutable, value-type) instead of mutable struct (heap, reference).
Concurrency deep dive: M:N scheduler — Julia tasks (coroutines) are multiplexed across Threads.nthreads() OS threads. @spawn schedules onto any thread; @spawnat :default is the same. Channel(N) is buffered; reading blocks the task (not the thread). ReentrantLock for shared state. Threads.@threads partitions a loop statically; OhMyThreads.jl and FLoops.jl give better composition. GPU: CUDA.jl (NVIDIA), AMDGPU.jl (ROCm), Metal.jl (Apple), oneAPI.jl — all expose CuArray/ROCArray/etc. that broadcast and dispatch like Array.
FFI: ccall((:fname, "libname"), RetT, (ArgT1, ArgT2), arg1, arg2) is the primitive. @ccall fname(arg::T)::RetT is the modern macro form. No header parsing needed; types map directly. Libdl for dlopen. Two-way: pass Julia closures to C with @cfunction. PythonCall.jl / PyCall.jl for Python; RCall.jl for R; JavaCall.jl, MATLAB.jl.
Reflection: rich.
methods(f)lists every method.methodswith(T)lists methods that takeT.subtypes(T),supertype(T).fieldnames(T),fieldtypes(T).isa(x, T),typeof(x).dump(x)prints recursive structure.
Performance tools:
@time,@allocated,@elapsed— quick checks.BenchmarkTools.jl:@btime,@benchmark— proper microbench (multiple samples, GC-aware).Profile.@profile(sampling profiler) +ProfileView.jl/PProf.jlfor flame graphs.JET.jl— static type-instability analyzer.Cthulhu.jl— interactive deep dive into type-inferred IR (@descend f(args)).
God mode
Macros: full Lisp-style on the AST. A macro receives quoted Expr objects and returns one.
macro twice(ex)
quote
$(esc(ex))
$(esc(ex))
end
end
@twice println("hi") # prints "hi" twiceExpansion is at parse time; inspect with @macroexpand @twice .... esc() controls hygiene (escape from macro’s gensym renaming).
Generated functions: emit different code per argument-type signature.
@generated function unrolled_sum(t::NTuple{N, T}) where {N, T}
expr = :(t[1])
for i in 2:N
expr = :($expr + t[$i])
end
expr
endRuns at compile time per signature; the returned Expr becomes the method body.
Compiler introspection — the four levels:
@code_lowered f(args)— desugared AST.@code_typed f(args)— after type inference; shows specialized SSA IR.@code_llvm f(args)— generated LLVM IR.@code_native f(args)— emitted assembly.
Multiple dispatch + invalidation: when you add a method, every cached method instance whose inference depended on “this generic was incomplete” gets invalidated and may need recompilation. SnoopCompile.jl finds invalidation chains; reducing them is essential for fast TTFX (time to first X).
Precompilation + sysimages: each package precompiles to native code on install. PackageCompiler.jl lets you bake your code (and a workload) into a custom sysimage (create_sysimage), eliminating JIT latency. create_app produces a relocatable executable; create_library a shared library callable from C.
ccall internals: ccall knows about the Julia ABI for Cint, Cdouble, Cstring, Ptr{T}, Ref{T}. Variadic via (args...,)::Cint. @ccall macro gives nicer syntax. Base.unsafe_load/unsafe_store! for raw pointer ops.
Type-stable code patterns: a function is type-stable if its return type is a function of its argument types alone. Anti-patterns: branches that return different types (x > 0 ? 1 : "neg"), reading globals not declared const, untyped fields in struct. Use @code_warntype f(args) — red Anys mean instability.
Distributed / Dagger: Distributed for explicit worker management; Dagger.jl builds a parallel task graph (delayed evaluation) that schedules across threads/workers/GPUs.
Idioms & style
- Naming:
lowercasewordsfor functions and modules (no separator:findnext,isvalid);CamelCasefor types/modules:MyType,LinearAlgebra.SCREAMINGfor constants. Suffix!on functions that mutate their first argument (push!,sort!). - Formatter:
JuliaFormatter.jl(format(".")). - Linter:
JET.jl(type-checker + linter),Aqua.jl(package quality),StaticLint.jl(LSP backend). - Idiomatic patterns:
- Define small, generic functions; let dispatch do the work.
- Prefer
Vector{T}with concreteToverVector{Any}. - Use
doblocks for callbacks:open("f") do io ... end. - Use
@viewsto avoid array copies on slicing. - Use broadcasting (
.) instead of explicit loops for elementwise ops.
- Expert review focus: type stability (
@code_warntype), allocation hotspots, invalidation cost of new method definitions,const-correctness of module globals, missingeltype/lengthmethods on custom iterables, abuse ofAny-typed containers, throwing in tight loops.
Ecosystem
- Numerical / Sci:
LinearAlgebra(stdlib),DifferentialEquations.jl(state-of-art ODE/PDE/SDE — composes with autodiff and units),JuMP.jl(mathematical programming),Optim.jl,NLopt.jl,IterativeSolvers.jl. - ML / AI:
Flux.jl(pure-Julia DL),Lux.jl(functional, explicit-state),MLJ.jl(sklearn-style frame),Transformers.jl,Turing.jl(probabilistic programming),SciML/SciMLSensitivity.jl(universal differential equations). - Autodiff:
ForwardDiff.jl,Zygote.jl,Enzyme.jl(LLVM-level reverse-mode, fastest),ReverseDiff.jl. - Data:
DataFrames.jl,Tables.jl(interface),CSV.jl,Arrow.jl,Parquet2.jl,Query.jl,DuckDB.jl. - Plotting:
Plots.jl(multi-backend),Makie.jl(high-perf, GPU-capable, publication-quality),Gadfly.jl(grammar of graphics),PlotlyJS.jl. - Web:
HTTP.jl,Genie.jl(full-stack framework),Oxygen.jl(FastAPI-like),Franklin.jl(static sites),Pluto.jl(reactive notebooks — kills Jupyter for Julia work). - Testing:
Test(stdlib,@testset,@test),ReTest.jl(selective),Aqua.jl(anti-pattern detection),JET.jl. - Docs:
Documenter.jlis canonical; docstrings ("""..."""above defs) are first-class. - Notable users: NASA (CSO models), Pfizer (Pumas pharmacometrics), Federal Reserve (DSGE models), Climate Modeling Alliance (CliMA), AstraZeneca, BlackRock (Aladdin numerics), MIT, CERN.
Gotchas
- Time-to-first-X (TTFX): JIT compilation latency on first call is a notorious pain point.
PackageCompiler.jlsysimages and the--compile=min --optimize=0flags help; pre-1.9 it was much worse. - 1-indexed arrays:
xs[1]is the first element.xs[end]is the last. Iteratingfor i in 1:length(xs)works butfor i in eachindex(xs)is safer (handles offset arrays). Vector{Any}is slow:[1, "a"]infersVector{Any}. Type-annotate or use aTuplefor heterogeneous data.- Globals must be
constto be type-stable in functions that read them. - Mutation in loops can de-specialize if you change a variable’s type partway through (write
x = 0; for ...; x += 1.0; end—xbecomesUnion{Int, Float64}). - Type piracy: defining a method on a type you don’t own and a function you don’t own. Breaks invalidation, surprises other packages.
@asyncon threaded runtime: pre-1.10,@asyncdid not migrate across threads; useThreads.@spawnexplicitly.- Broadcasting fusion:
sin.(cos.(xs))fuses into one loop;sin.(cos.(xs)) .+ 1also fuses. But assigning to a temporary breaks fusion. - Integer overflow is silent:
typemax(Int) + 1 == typemin(Int). UseBase.checked_addorBigIntfor safety. ==vs===vsisequal:==is value equality with NaN!=NaN;===is bitwise/identity;isequaltreats NaN==NaN, used byDict/Set.missingpropagation:1 + missing == missing,missing == missing == missing(nottrue!). Useismissing(x).- Pkg environment confusion: forgetting
]activate .means installing into the default@v1.xshared env, polluting it. include("file.jl")is order-dependent — there are no header files. The Revise.jl workflow is essential for not restarting Julia on every change.
Citations
- Julia documentation (manual + stdlib): https://docs.julialang.org/en/v1/
- Julia Performance Tips: https://docs.julialang.org/en/v1/manual/performance-tips/
- Julia Style Guide: https://docs.julialang.org/en/v1/manual/style-guide/
- Multiple Dispatch (Karpinski JuliaCon talk): https://www.youtube.com/watch?v=kc9HwsxE1OY
- Pkg.jl docs: https://pkgdocs.julialang.org/v1/
- General registry: https://github.com/JuliaRegistries/General
- juliaup installer: https://github.com/JuliaLang/juliaup
- PackageCompiler.jl: https://julialang.github.io/PackageCompiler.jl/dev/
- BenchmarkTools.jl: https://juliaci.github.io/BenchmarkTools.jl/stable/
- Documenter.jl: https://documenter.juliadocs.org/stable/
- SciML org (DifferentialEquations etc.): https://sciml.ai/
- Wikipedia (creators, dates, license): https://en.wikipedia.org/wiki/Julia_(programming_language)