# Using Module names for dispatch

**URL:** <https://discourse.julialang.org/t/using-module-names-for-dispatch/25010>\
**Category:** General Usage\
**Created:** [June 6, 2019, 2:43pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010 "2019-06-06T14:43:08Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [June 6, 2019, 2:43pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/1 "2019-06-06T14:43:08Z")

</div>

I’m working on a metapackage (HermitianDiagonalization.jl) that implements a bunch of methods based on the functionality of some third-party packages (Arpack, ArnoldiMethod, etc…), provided they have been loaded by the user. I’m using Requires.jl for this. There is one bit of functionality I’m struggling to get working.

I want to write a function `diagonalizer(matrix, packagename::Module)` that does different things on a `matrix` depending on `packagename` of a loaded package, or throw an error if the package was not loaded. How can I achieve this? (I would also appreciate an answer of the sort “you’re approaching this completely wrong, try this instead”). Thanks!

### What I tried

I thought about using Julia’s dispatch machinery. Now, `packagename isa Module`, such as `Arpack`. I cannot dispatch on different `packagename`s, because they are not different types themselves, they are just different objects of type `Module`. I could just try to use an `if-elseif` construct, such as

```julia-auto
if packagename == Arnoldi
    ...
elseif packagename == KrylovKit
    ...
...
end

```

But of course this doesn’t work, because the symbols `Arnoldi`, `KrylovKit` etc need not be defined in any given session (if the user didn’t load them). I also tried building a `defaultmethods = Dict{Module,Function}` as part of the Requires machinery, but if the module is loaded _after_ loading my package, it does not trigger `push!` of the new module into `defaultmethods`, so no dice… I cannot seem to figure this one out!

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [June 6, 2019, 2:57pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/2 "2019-06-06T14:57:13Z")

</div>

I believe the old method used to be to dispatch on `Val(:something)` but now with constant propagation you can just do `diagonalizer(A,:arpack)` and check with an `if` in your function. The check will be compiled away and the method will be type-stable.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [June 6, 2019, 2:59pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/3 "2019-06-06T14:59:21Z")

</div>

So there is no way to use `Arpack` (the `Module` name itself), instead of `:arpack`?

I found it quite appealing and simple to have an API like `using Arpack; diagonalizer(m, Arpack)`… No need to remember/find out extra information on valid arguments…

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [June 6, 2019, 3:03pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/4 "2019-06-06T15:03:34Z")

</div>

You can see for yourself what you can do with a module name:

`julia> methodswith(typeof(Base))`

There’s a number of things there, but in particular `fullname` should get you what you want.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [June 6, 2019, 3:06pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/5 "2019-06-06T15:06:45Z")

</div>

> [@antoine-levitt](#):
>
> `fullname` should get you what you want.

Nice one! So something like the following, yes? Thanks!

```julia
function diagonalizer(a, m::Module)
   name = first(fullname(m))
   if name == :Arpack
   elseif name == ...
   ...
   end
end

```

---

<div class="post-metadata">

**Author:** ![jpsamaroo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpsamaroo/32/46804_2.png) [@jpsamaroo](https://discourse.julialang.org/u/jpsamaroo)\
**Post date:** [June 6, 2019, 4:20pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/6 "2019-06-06T16:20:07Z")

</div>

> [@pablosanjose](#):
>
> function diagonalizer(a, m::Module) name = first(fullname(m)) if name == :Arpack elseif name == … … end end

If you want to be able to dispatch on the module name, this should work:

```julia
function diagonalizer(a, m::Module)
   diagonalizer(Val(first(fullname(m))))
end
function diagonalizer(a, m::Val{:Arpack})
  # Do Arpack-specific things
end
# more dispatches go here...

```

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [June 6, 2019, 5:28pm UTC](https://discourse.julialang.org/t/using-module-names-for-dispatch/25010/7 "2019-06-06T17:28:58Z")

</div>

@jpsamaroo, that’s exactly what I ended up doing. Constant propagation even makes it inferable. Thanks to both, this community is amazing.

EDIT: my bad, I’m afraid inference is not able to figure this out by constant prop; looking into it.
