avatarEmma Boudreau

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3882

Abstract

p id="0f52">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:</p><div id="9868"><pre><span class="hljs-attr">x</span> = [<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>] <span class="hljs-attr">y</span> = [<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>]</pre></div><p id="f25d">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 <code>.</code> to our normal operators, the first of which being +=:</p><div id="452a"><pre><span class="hljs-attribute">x</span> .+= <span class="hljs-number">5</span> <span class="hljs-attribute">y</span> .+= <span class="hljs-number">5</span></pre></div><p id="7c15">Now we will multiply the two:</p><div id="a548"><pre>x .* y <span class="hljs-number">3</span>-element <span class="hljs-built_in">Vector</span>{<span class="hljs-built_in">Int64</span>}: <span class="hljs-number">100</span> <span class="hljs-number">225</span> <span class="hljs-number">400</span></pre></div><p id="941c">This 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.</p><h2 id="55ae">How this connects to broadcasting</h2><p id="f4ef">Any function inside of Julia can be broadcasted instantly using the <code>@.</code> macro. This macro takes the function call after it and broadcasts it to our arguments using the <code>broadcast</code> method. While the operators are able to use this . syntax, typically instead in Julia we will use <code>@.</code> . For example,</p><div id="49c6"><pre><span class="hljs-meta prompt_">julia></span><span class="language-julia"> sub1(x::<span class="hljs-built_in">Int64</span>) = x - <span class="hljs-number">1</span> </span>sub1 (generic function with 1 method)</pre></div><div id="d2b8"><pre><span class="hljs-meta prompt_">julia></span><span class="language-julia"> .sub1([<span class="hljs-number">5</span>, <span class="hljs-number">10</span>]) </span>ERROR: syntax: invalid identifier name "." Stacktrace: [1] top-level scope @ none:1</pre></div><div id="8632"><pre><span class="hljs-meta prompt_">julia></span><span class="language-julia"> @. sub1([<span class="hljs-number">5</span>, <span class="hljs-number">10</span>]) </span>2-element Vector{Int64}: 4 9</pre></div><p id="f815">The 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.</p><h2 id="08a4">Broadcasting</h2><p id="f12d">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 <code>Function</code> and <code>Any ...</code> 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:</p><div id="f9d3"><pre><span class="hljs-attr">x</span> = [<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>]</pre></div><p id="6e06">Here is a simple addition function which will concatenate each integer to a st

Options

ring:</p><div id="b3f3"><pre><span class="hljs-keyword">function</span> concattos(x::<span class="hljs-built_in">Int64</span>, s::<span class="hljs-built_in">String</span>) <span class="hljs-string">"<span class="hljs-variable">s</span><span class="hljs-variable">x</span>"</span> <span class="hljs-keyword">end</span></pre></div><p id="91a4">We can broadcast it and provide our arguments like so:</p><div id="4623"><pre><span class="hljs-function"><span class="hljs-title">broadcast</span><span class="hljs-params">(concattos, x, <span class="hljs-string">"hello number "</span>)</span></span></pre></div><div id="fe3b"><pre><span class="hljs-number">3</span>-element <span class="hljs-built_in">Vector</span>{<span class="hljs-built_in">String</span>}: <span class="hljs-string">"hello number 5"</span> <span class="hljs-string">"hello number 10"</span> <span class="hljs-string">"hello number 15"</span></pre></div><p id="7bf8">The <code>broadcast</code> 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 <code>DimensionMismatch</code> . Here is this example, but now including an additional vector:</p><div id="155c"><pre><span class="hljs-keyword">function</span> concattos(x::<span class="hljs-built_in">Int64</span>, s::<span class="hljs-built_in">String</span>, x2::<span class="hljs-built_in">Int64</span>) <span class="hljs-string">"<span class="hljs-variable">s</span><span class="hljs-variable">x</span> or <span class="hljs-variable">$x2</span>"</span> <span class="hljs-keyword">end</span></pre></div><div id="a730"><pre><span class="hljs-function"><span class="hljs-title">broadcast</span><span class="hljs-params">(concattos, x, <span class="hljs-string">"hello number "</span>, [<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>])</span></span></pre></div><div id="48b2"><pre><span class="hljs-number">3</span>-element <span class="hljs-built_in">Vector</span>{<span class="hljs-built_in">String</span>}: <span class="hljs-string">"hello number 5 or 5"</span> <span class="hljs-string">"hello number 10 or 10"</span> <span class="hljs-string">"hello number 15 or 15"</span></pre></div><p id="ad5e">The last method we are going to look at is <code>broadcast!</code> . This method is very similar to broadcast!, although the usage is just slightly different, and of course the function itself is mutating.</p><div id="a0cd"><pre><span class="hljs-attribute">B</span> =<span class="hljs-meta"> [0.0; 0.0]</span> <span class="hljs-attribute">A</span> =<span class="hljs-meta"> [1.2; 7.5]</span> <span class="hljs-attribute">broadcast</span>!(+, B, A, (<span class="hljs-number">0</span>, -<span class="hljs-number">2</span>.<span class="hljs-number">0</span>));</pre></div><div id="ae1e"><pre><span class="hljs-function"><span class="hljs-title">println</span><span class="hljs-params">(B)</span></span> <span class="hljs-selector-attr">[1.2, 5.5]</span></pre></div><h1 id="ac68">Conclusion</h1><p id="c9ab">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.</p><p id="67fb">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!</p></article></body>

Broadcasting POWER In Julia: Beginner Friendly Overview

A simple introduction to broadcasting in Julia.

image by geralt on pixabay

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 .+= 5

Now we will multiply the two:

x .* y
3-element Vector{Int64}:
 100
 225
 400

This 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:1
julia> @. sub1([5, 10])
2-element Vector{Int64}:
 4
 9

The 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"
end

We 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"
end
broadcast(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!

Data Science
Programming
Julia
Coding
Software Development
Recommended from ReadMedium