Broadcasting POWER In Julia: Beginner Friendly Overview
A simple introduction to broadcasting in Julia.

Introduction
Vectors: probably one of the most common structures to work with in programming. Vectors are the quintessential and basic iterable that comes in the Base of the Julia language. It is likely we have all worked with Vectors! However, there are several different techniques one may use to make changes and mutate these Vectors into the sort of data that we might want. One example of such a technique is the typical approach; iteration.
Iteration certainly has its examples, the biggest advantage probably being the access to iteration-exclusive key-words and expressions. Some examples of those are break and continue. If you would like to learn more about those sorts of approaches to iteration, here is another article I wrote that goes into detail on break and continue:
However, iteration does have a pretty significant drawback, and that is performance. To be clear, there is nothing wrong with using iteration at all, it is just that each time iteration happens, the thread is stalled unless a new thread is spawned to create the loop. In other words, any sort of operation on a collection is going to stall the process. Fortunately, there are a few alternatives to iteration that we can use.
One such alternative is using a comprehension, which is technically broadcasting in Julia. Comprehensions are actually an incredibly quick way to replace iteration in a lot of instances in Julia. If you would like to learn more about Julian comprehensions, I also have a really awesome article on those which you may read here!:
While comprehensions are great, and are a great branch-off from the concepts we are going to be talking about here, today the focus is on doing these operations instead with broadcasting. Broadcasting is a technique that allows us to apply a given function to an infinite number of arguments. In essence, we can use this technique to vectorize methods and arguments and modify many different things at once.
notebook
Broadcasting operators
Another topic we also might want to add to this conversation, as from review we will receive a better idea of broadcasting and what this ends up going to in Base. Let us look at some examples of different operators, then broadcast them to two arrays:
x = [5, 10, 15]
y = [5, 10, 15]What we want to do is broadcast a few changes to these two arrays. First, I want to add 5 to each values, then I want to get the product. This starts by adding a . to our normal operators, the first of which being +=:
x .+= 5
y .+= 5Now we will multiply the two:
x .* y
3-element Vector{Int64}:
100
225
400This basic set of examples gives a pretty good idea of what broadcasting does. Instead of applying something to a particular value, it can be provided to infinite arguments. It is a mistake to assume that this is operator specific, however, the . operators are actually constructed of two unique properties, the . and the operator.
How this connects to broadcasting
Any function inside of Julia can be broadcasted instantly using the @. macro. This macro takes the function call after it and broadcasts it to our arguments using the broadcast method. While the operators are able to use this . syntax, typically instead in Julia we will use @. . For example,
julia> sub1(x::Int64) = x - 1
sub1 (generic function with 1 method)julia> .sub1([5, 10])
ERROR: syntax: invalid identifier name "."
Stacktrace:
[1] top-level scope
@ none:1julia> @. sub1([5, 10])
2-element Vector{Int64}:
4
9The vectorization of functions is incredibly useful in Julia, and an incredibly awesome feature that I have not seen implemented very often into a language’s Base. This can save a ton of processing time when working with large collections! The beauty of this syntax is made possible by broadcasting.
Broadcasting
The final piece of this puzzle is broadcasting. What broadcasting itself does is maps a function across an infinite number of arguments. The broadcast function takes a Function and Any ... as its two positional arguments. We can use this the broadcast a function to a type or Vector, just as before, however this time we have a few more options. Consider our new old x:
x = [5, 10, 15]Here is a simple addition function which will concatenate each integer to a string:
function concattos(x::Int64, s::String)
"$s$x"
endWe can broadcast it and provide our arguments like so:
broadcast(concattos, x, "hello number ")3-element Vector{String}:
"hello number 5"
"hello number 10"
"hello number 15"The broadcast method will essentially take the current element of any collection, and provide it as an argument for each element. Arguments which are vectorized are broken down and the function is called for each dimension which the vectors might have. If the dimensions are different, we will get a DimensionMismatch . Here is this example, but now including an additional vector:
function concattos(x::Int64, s::String, x2::Int64)
"$s$x or $x2"
endbroadcast(concattos, x, "hello number ", [5, 10, 15])3-element Vector{String}:
"hello number 5 or 5"
"hello number 10 or 10"
"hello number 15 or 15"The last method we are going to look at is broadcast! . This method is very similar to broadcast!, although the usage is just slightly different, and of course the function itself is mutating.
B = [0.0; 0.0]
A = [1.2; 7.5]
broadcast!(+, B, A, (0, -2.0));println(B)
[1.2, 5.5]Conclusion
Julia has a pretty rad broadcasting system that in my experience works incredibly well. This concept feels pretty approachable, and it is easy to see why broadcasting functions instead of opening iterative loops all of the time can certainly be useful. Another aspect to this that we merely touched on is comprehensions, which is essentially broadcasting broadcasting and is super cool.
These are techniques I use all of the time and to great effect in my code, so I really hope the same will be said for you! Thank you for your time, I appreciate it, and have a wonderful time trying this in your next project!
