Methods in Julia

Adarsh Ms
The Startup
Published in
4 min readSep 5, 2020

Broadcasting, methods and multiple-dispatch

This is part 9 of the Julia Tutorials (a series of tutorials on Julia). If you are not familiar with Julia functions, please go through part 8 for better understanding.

If you are not familiar with Julia and want to get started with it, feel free to check out the complete series @ —

Note: Use Julia’s REPL to quickly follow along with the codes in this tutorial

Broadcasting

Broadcasting in Julia helps to write performant code. Think of an application where you want to update an iterable such as an array element-wise, the most straight forward approach is iterating through each entry of the array using a for loop and updating them. But, this can be made more efficient by using Julia’s built-in broadcasting operators. We can apply broadcasting on both Julia’s built-in and user defined functions. Broadcasting can be done in 2 ways:

Using broadcast keyword

function increment(a, factor=1)
a += factor
end
arr = [1, 2, 3, 4, 5, 6, 7]# Broadcast the increment function over the array
arr = broadcast(increment, arr)

In the above example, the increment function updates the value of the argument a by factor . So when increment is broadcasted over the array arr , each element of arr gets incremented by factor .

If you want to broadcast over only a certain arguments, it can be done like this:

arr = broadcast(i -> increment(i, 2), arr)

Using . (vectorized dot) operator
If you have gone through part 6 of this tutorial series (Operators in Julia), you would probably remember about the vectorized dot operator. Let’s see how we can broadcast our increment function over arr using . operator.

arr = increment.(arr)

For broadcasting over only certain arguments, wrap the arguments that shouldn’t be broadcasted inside Ref

arr = increment.(Ref(2), arr)

Methods and Multiple-Dispatch

When same kind of operation needs to be done for different argument types, we can define the same function with different number and types of arguments. i.e, in the case of adding 2 numbers, we can implement the same addition logic in 2 different functions (with same name and different argument types), one for floating point addition and another for integer addition.

Julia provides such a functionality by which different implementations of the same concept can be implemented easily. Each of these implementations can have different argument type combinations and different behaviors associated with them. The definition of one of these behaviors is termed as a method.

In Julia, each time a function is called, the most appropriate method is applied based on it’s arguments. Applying a method when calling a function is known as dispatch. Object-oriented languages ​​traditionally only consider the first argument in dispatch. Julia is different in that it takes all the arguments of the function into account (not just the first) and then chooses which method to call. This is known as multiple dispatch.

Multiple dispatch is used by almost all built-in functions and operators in Julia. For example, Julia’s * perform different operations for different types, for numeric types, it involves multiplication, while for strings, it means string concatenation.

# with numeric types
3 * 2 # Yields 6
3.5 * 2 # Yields 7
# with string types
"Good" * " morning" # Yields "Good morning"

To make use of multiple dispatch in our program, we can construct our own methods for a function. Creating a method is pretty much similar to creating a function.

Let’s implement different methods for a function to add it’s arguments.

# Method 1
add(x::Number, y::Number) = x + y
# Method 2
function add(x::String, y::String)
println("Method 2 invoked")
return "$x $y"
end
# Method 3
function add(x, y::String)
println("Method 3 invoked")
return "$x$y"
end
# Method 4
function add(x::String, y)
println("Method 4 invoked")
return "$x-$y"
end

In the above example, we have declared 4 methods where:

  • Method 1: Adds arguments x and y if they are of type Number
  • Method 2: Merge arguments separated by a white space if they are of type String
  • Method 3: Merge arguments if the 1st argument is of type Any and the 2nd one a String
  • Method 4: Merge arguments separated by a - if the 1st argument is of type String and the 2nd one is Any

Julia provides methods keyword which returns all the methods constructed for a function. In our example, if we call methods on add , we will get the following:

# 4 methods for generic function "add":
[1] add(x::String, y::String) in Main at REPL[2]:2
[2] add(x::Number, y::Number) in Main at REPL[1]:1
[3] add(x, y::String) in Main at REPL[3]:2
[4] add(x::String, y) in Main at REPL[4]:2

Now, let’s see how Julia uses multiple dispatch to call our method of best fit.

add(1, 2)                        # Invokes Method 1
add("Good", "morning") # Invokes Method 2
add(4, "ever") # Invokes Method 3
add("method", 4) # Invokes Method 4

As you can see, When a function is called, Julia finds the best possible method defined for that function based on all the argument types (and not just the first argument) and invokes the most specialized method available.

--

--

Adarsh Ms
The Startup

A passionate engineer who thrives on using programming languages to converse with machines.