Arrays and broadcasting in depth

Build arrays of the right shape, slice without copying using views, and understand how broadcasting fuses into a single loop.

Building and inspecting arrays

zeros(3)                 # Vector{Float64}, length 3
ones(Int, 2, 3)          # 2x3 Matrix{Int}
fill(7, 4)
[1, 2, 3]                # Vector{Int}
[1 2 3]                  # 1x3 Matrix{Int}
[1 2; 3 4]               # 2x2 Matrix

A = reshape(1:12, 3, 4)  # column-major: columns fill first
ndims(A), size(A), length(A)
A[2, 3]                  # row 2, column 3
A[7]                     # linear index, column-major order
axes(A)                  # (Base.OneTo(3), Base.OneTo(4))

Julia stores arrays in column-major order, matching Fortran and BLAS. It matters for cache behaviour: iterating down a column is fast, iterating across a row jumps through memory.

Views and copies

ExpressionResult
A[1:3, :]A new array, copied
view(A, 1:3, :)A SubArray pointing at the same memory
@view A[:, 2]Same, with macro syntax
@views A[:, 2] .+ 1Every index in the expression becomes a view
reshape(A, 4, 3)A new shape over the same memory
permutedims(A)A transposed copy with real dimensions
A'A lazy adjoint; multiplies efficiently, prints correctly
A = reshape(1.0:12.0, 3, 4)

col = @view A[:, 2]
col[1] = 99.0
A[1, 2]                  # 99.0 - the view wrote into the parent

copy(col)                # an independent array
B = A'                   # adjoint, not a transposed copy
size(B), typeof(B)

sum(A; dims = 1)         # reduce along dimension 1, keeping the dimension
dropdims(sum(A; dims = 1), dims = 1)
  • A view avoids a copy, so it is faster, and it also aliases: writing through it modifies the original.
  • sum(A; dims = 1) returns a 1x4 matrix, not a vector. Wrap it in vec() or use dropdims when you need a vector.
  • @views on a whole expression is the idiomatic way to avoid copies in numerical code without cluttering every line.

Broadcasting and fusion

x = rand(10^6)
y = rand(10^6)

# one fused loop, no intermediate arrays
z = sqrt.(x .^ 2 .+ y .^ 2)

# equivalent to
z2 = @. sqrt(x^2 + y^2)

# broadcasting aligns dimensions, and singleton dimensions expand
m = rand(3, 1)
v = rand(1, 4)
m .+ v                   # 3x4: both singleton dimensions are stretched

# reduce over a broadcast without materialising it
sum(abs2, x)             # faster and cleaner than sum(abs2.(x))
⚠️
Broadcasting fuses a whole expression, so a single mistake inside it produces one error for the entire chain. Add explicit parentheses or split a long chain into two lines when the error is hard to locate, and remember that a dotted call still allocates its result array.

FAQ

When should I use @view instead of a slice?
Use a view when the slice is read-only, large, or used inside a loop. Use a plain slice when the code that follows writes to it and you meant to leave the original untouched.
Why does sum(A; dims=1) return a matrix?
Reductions keep the reduced dimension as size one, which makes the result broadcastable against the original array. Call vec() when you want a plain vector.

Control flow, loops and comprehensions Syntax and the type system

Last refreshed 2026-09-18.