Dot Syntax: Element-wise Operations
Prerequisites: Functions
Adding a dot applies any function or operator to every element of an array. This is called broadcasting:
xs = [1, 2, 3, 4]
println(xs .* 10)
println(xs .^ 2)
println(xs .+ [10, 20, 30, 40])
println(sqrt.(xs))
println(uppercase.(["a", "b"]))
f(x) = 3x + 1
println(f.(xs))
println(xs .> 2)
println(xs[xs .> 2])
[10, 20, 30, 40]
[1, 4, 9, 16]
[11, 22, 33, 44]
[1.0, 1.4142135623730951, 1.7320508075688772, 2.0]
["A", "B"]
[4, 7, 10, 13]
Bool[0, 0, 1, 1]
[3, 4]
.+,.*,.^,.>are the element-wise versions of operators.f.(xs)calls any function — including your own — on each element. Nothing special needs to be written inf.xs[xs .> 2]selects elements with a vector oftrue/falsevalues (a mask).
Why the dot is needed
Without the dot, operations mean their mathematical meaning for arrays, which isn't always element-wise:
v = [1, 2, 3]
println(v * 2)
println(v + v)
try
v * v
catch err
println("v * v fails: ", typeof(err))
end
println(v .* v)
try
sqrt(v)
catch err
println("sqrt(v) fails: ", typeof(err))
end
[2, 4, 6]
[2, 4, 6]
v * v fails: MethodError
[1, 4, 9]
sqrt(v) fails: MethodError
Multiplying two column vectors isn't defined in linear algebra, so
v * v is an error — you have to say v .* v. This makes your intent
explicit.
@. adds the dots for you
x = [0.0, 0.5, 1.0]
y1 = 2 .* x .^ 2 .+ 3 .* x .+ 1
y2 = @. 2x^2 + 3x + 1
println(y1)
println(y1 == y2)
[1.0, 3.0, 6.0]
true
@. puts a dot on every operation and call in the expression. Julia
also fuses a chain of dotted operations into a single loop, so no
temporary arrays are created along the way.
Scalars and arrays together
Broadcasting stretches single values to match arrays:
prices = [9.99, 24.50, 5.00]
with_tax = round.(prices .* 1.2, digits = 2)
println(with_tax)
println(string.("item", 1:3))
[11.99, 29.4, 6.0]
["item1", "item2", "item3"]
Level 2 goes further: broadcasting across matrices, rows, and columns.
Practice
Given c = [-10, 0, 25, 37] (degrees Celsius), compute Fahrenheit
(9/5 * c + 32) with @., and print only the values above 50.
Show solution
c = [-10, 0, 25, 37]
f = @. 9 / 5 * c + 32
println(f)
println(f[f .> 50])
[14.0, 32.0, 77.0, 98.60000000000001]
[77.0, 98.60000000000001]