Possible ambiguities during dispatch 

Of course, we can always define all possible methods with concrete type arguments; however, that may not be the most desirable option when designing software. Why? It's because the number of combinations in argument types could be overwhelming, and it is often unnecessary to enumerate them all. In our game example here, we only need to detect collisions between two types—spaceship and asteroid. So we just need to define 2 x 2 = 4 methods; however, imagine what we would do when we have 10 types of object. We would then have to define 100 methods!

The idea of abstract types can save us. Let's just imagine that we do have to support 10 concrete data types. If the other eight data types have similar shapes, then we could cut down the number of methods tremendously by accepting an abstract type as one of the arguments. How? Let's take a look:

function collide(A::Asteroid, B::Thing)
println("Checking collision of asteroid vs. thing")
return true
end

function collide(A::Thing, B::Asteroid)
println("Checking collision of thing vs. asteroid")
return false
end

These two functions provide the default implementation for detecting collisions between an Asteroid and any Thing. The first method can handle the first argument being Asteroid and the second argument being any subtype of Thing. If we were to have 10 concrete types in total, this single method can handle 10 scenarios. Likewise, the second method can handle the other 10 scenarios. Let's just have a quick check:

Great! these two calls are working fine. Let's finish our test:

But wait, what happened when we tried to check the collision between two asteroids? Well, the Julia runtime has detected an ambiguity here. When we pass two Asteroid arguments, it is unclear whether we want to execute collide(A::Thing, B::Asteroid) or collide(A::Asteroid, B::Thing). Both methods seem to be able to take the task, but neither of their signatures is narrower than the other, and so it just gave up and throws an error. 

Fortunately, it actually suggested a fix as part of the error message. A possible fix is to define a new method, collide(::Asteroid, ::Asteroid), as follows:

function collide(A::Asteroid, B::Asteroid)
println("Checking collision of asteroid vs. asteroid")
return true # just a test
end

Because it has the narrowest signature, Julia can properly dispatch to this new method when two asteroids are passed to the collide function. Once this method is defined, there will be no more ambiguity. Let's try again. The result is as follows:

As you can see, when you encounter ambiguity for multiple dispatch, it can be resolved easily by creating a function with more specific types in its arguments. The Julia runtime will not try to guess what you want to do. As a developer, we need to provide clear instructions to the computer.

However, ambiguities may not be obvious from just looking at the code. In order to reduce the risk of hitting the problem at runtime, we can proactively detect which part of the code may introduce such ambiguities. Fortunately, Julia already provides a convenient tool to identify ambiguities. We will take a look at that in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.230.81