Julia
Python's ease with C's speed, for science and ML.
Julia was designed for fast numerical and scientific computing. It looks like Python or MATLAB but compiles to fast native code, which is why it is used for climate models, pharmaceutical simulations and differentiable machine learning with Flux and Lux.
Why learn Julia?
Julia solves the two-language problem: you can prototype and run production-speed numerical code in the same language.
- Fast: JIT compilation gives near-C speed for loops.
- Built for maths: arrays, linear algebra and Unicode maths symbols are first-class.
- ML and GPUs: Flux, Lux and CUDA.jl run neural networks on NVIDIA GPUs.
Set up and run your first program
Install Julia with juliaup from julialang.org, then use the REPL or VS Code.
julia --version
julia hello.jlname = "Ada"
println("Hello, AI! Welcome to Julia, $name.")] in the REPL to enter package mode, then add Flux to install packages.Variables and numbers
No declarations needed. Julia has many numeric types (Int64, Float32, Float16, BigInt) and you can write 2x for 2 * x.
layers = 32
lr = 3e-4
params = 8_030_000_000
x = Float16(0.1) # half precision, like on GPUs
println("FP16 size: ", params * 2 / 1e9, " GB")
println(typeof(x), " ", 2layers)Arrays and broadcasting
Arrays are 1-indexed and column-major. A dot (.) broadcasts any function over every element, with no loops.
w = [0.5, -1.0, 2.0, 0.25]
println(w .* 2) # element-wise
println(sum(w .^ 2))
A = rand(3, 3)
v = rand(3)
println(A * v) # matrix-vector product
println(size(A), " ", w[1]) # first element is index 1Functions and multiple dispatch
Functions can have several methods chosen by the types of all arguments. This multiple dispatch is Julia's central idea.
params(layers, width=4096) = 12 * layers * width^2
describe(x::Integer) = "an integer"
describe(x::AbstractFloat) = "a float"
describe(x::String) = "text"
println(params(32))
println(describe(8), ", ", describe(8.0), ", ", describe("fp8"))Control flow and comprehensions
Loops and conditionals end with end. Comprehensions build arrays in one line.
for epoch in 1:3
println("epoch ", epoch)
end
bits = 8
name = bits == 16 ? "FP16" : bits == 8 ? "FP8" : "other"
squares = [i^2 for i in 1:5 if isodd(i)]
println(name, " ", squares)Structs and types
struct defines immutable types (mutable struct for mutable ones). Methods are defined outside the struct.
struct Gpu
name::String
vram_gb::Int
end
fits(g::Gpu, gb) = gb <= g.vram_gb
Base.show(io::IO, g::Gpu) = print(io, g.name, " (", g.vram_gb, " GB)")
g = Gpu("H100", 80)
println(g, " fits 70 GB: ", fits(g, 70))AI with Julia
Julia is used for scientific machine learning, where neural networks are combined with physics models, and for fast research code. Automatic differentiation works on ordinary Julia code, and CUDA.jl runs it on GPUs.
The essential libraries
Gradient descent from scratch
Thanks to broadcasting, the gradient is one line per parameter.
x = range(-1, 1, length=100)
y = 3 .* x .+ 0.5 .+ 0.1 .* randn(100)
w, b, lr = 0.0, 0.0, 0.1
for step in 1:500
err = (w .* x .+ b) .- y
global w -= lr * sum(2 .* err .* x) / length(x)
global b -= lr * sum(2 .* err) / length(x)
end
println("w = ", round(w, digits=2), ", b = ", round(b, digits=2))Build an AI agent in Julia
HTTP.jl and JSON3.jl handle requests and messages. The loop sends tools to a local model and runs any tool it calls.
using HTTP, JSON3 # ] add HTTP JSON3
get_weather(city) = "It is 24°C and sunny in $city."
tools = [Dict("type" => "function", "function" => Dict("name" => "get_weather",
"description" => "Weather for a city",
"parameters" => Dict("type" => "object", "properties" => Dict("city" => Dict("type" => "string")),
"required" => ["city"])))]
messages = Any[Dict("role" => "user", "content" => "Should I take an umbrella in Lahore today?")]
for round in 1:5
res = HTTP.post("http://localhost:11434/v1/chat/completions", ["Content-Type" => "application/json"],
JSON3.write(Dict("model" => "llama3.1", "messages" => messages, "tools" => tools)))
msg = JSON3.read(res.body).choices[1].message
push!(messages, msg)
calls = get(msg, :tool_calls, [])
if isempty(calls)
println(msg.content); break
end
for call in calls
args = JSON3.read(call.function.arguments)
push!(messages, Dict("role" => "tool", "tool_call_id" => call.id, "content" => get_weather(args.city)))
end
endPromptingTools.jl offers a higher-level API with tool calling across providers.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.Julia learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
Julia cheat sheet
| Task | Syntax |
|---|---|
println("x = $x") | |
| Array | v = [1, 2, 3] |
| Broadcast | v .* 2 |
| Function | f(x) = x^2 |
| Struct | struct P; x::Int; end |
| Comprehension | [i^2 for i in 1:5] |
Common mistakes
- Arrays start at index 1.
- The first call of a function is slow because it compiles; time the second call.
- Changing a variable's type inside a loop (type instability) slows code down.
Where to go next
- Julia docs — official
- Flux.jl — deep learning
- JuliaAcademy — free courses
On TensorCore.si: Python volume, MATLAB volume.
Keyboard: [ previous language · ] next language · / search the library