# How to find if a method is implemented for an interface?

**URL:** <https://discourse.julialang.org/t/how-to-find-if-a-method-is-implemented-for-an-interface/636>\
**Category:** General Usage\
**Created:** [November 29, 2016, 7:04pm UTC](https://discourse.julialang.org/t/how-to-find-if-a-method-is-implemented-for-an-interface/636 "2016-11-29T19:04:36Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 29, 2016, 10:18pm UTC](https://discourse.julialang.org/t/how-to-find-if-a-method-is-implemented-for-an-interface/636/6 "2016-11-29T22:18:48Z")

</div>

`method_exists` and `applicable` may work depending on the use case. But note that checking `method_exists` happens at runtime, which may not be what you want. Here’s a more complicated but possibly more performant option (depending on whether compile-time enhancements out-weigh the cost of compilation) by mixing `method_exists` with traits.

In JuliaDiffEq, our interface for providing extra functions is [by adding additional dispatches](https://juliadiffeq.github.io/DiffEqDocs.jl/latest/features/performance_overloads.html#Other-Available-Functions-1). Because this was very important to us, we came up with a way to check for the existence of dispatches that will actually work at compile time (i.e. if you check the `@code_llvm`, the function `has_jac(f)` (checks if the Jacobian dispatch exists) will compile down to a true/false, and in codes which use `if has_jac(f)` the inappropriate branch will compile away and no checking needs to be done at runtime).

You can see the PR with how we came about the solution here:

> <https://github.com/SciML/DiffEqBase.jl/pull/2#issuecomment-261452685>
>
> I got it!
> 
> \`\`\` julia
> @traitdef HasJac{F}
> \_\_has\_jac(f) = check\_first\_arg(f, Val{:…jac})
> @generated SimpleTraits.trait{F}(::Type{HasJac{F}}) = \_\_has\_jac(F) ? :(HasJac{F}) : :(Not{HasJac{F}})
> has\_jac{T}(f::T) = istrait(HasJac{T})
> \`\`\`
> 
> Only check the methods table to generate the trait and you're good. Now it auto-finds the trait and \`has\_jac\` is the right value. Thanks for the help!

It makes use of @mauro3 's SimpleTraits.jl. Let me spell it out in more detail since it’s a little tricky.

@mauro3 provided the code which uses `method_exists` to see if a method exists by checking the first arg for a certain type (you can see in the docs that our interface has a value-type in front for each “extra dispatch”)

```julia
check_first_arg(f,T::Type) = check_first_arg(typeof(f),T)
function check_first_arg{F}(::Type{F}, T::Type)
    typ = Tuple{Any, T, Vararg}
    for m in Base.MethodList(F.name.mt) # F.name.mt gets the method-table
        m.sig<:typ && return true
    end
    return false
end

```

However, if you `@code_llvm` that, you’ll see that (because I think the MethodList is global?) that the code is huge and it actually is not as fast as you’d hope. So then we use an internal function:

```julia
__has_jac(f) = check_first_arg(f, Val{:jac})

```

to check for the dispatch, and use that internal function to apply a trait:

```julia
@traitdef HasJac{F}
@generated SimpleTraits.trait{F}(::Type{HasJac{F}}) = __has_jac(F) ? :(HasJac{F}) : :(Not{HasJac{F}})

```

Since checking for traits is a compile-time check, the following is then what we really wanted:

```julia
has_jac{T}(f::T) = istrait(HasJac{T})

```

In the end, `@code_llvm` compiles `has_jac(f)` to either be a true or a false, and everything works at compile time.

Of course, this can be major overkill depending on your use case. However, we found this solution useful since it allows us to have different branches (and dispatches due to traits) which fully optimize and are type-stable thanks to the fact that the existence of the method ends up as compile-time information.

---

_[View the full topic](https://discourse.julialang.org/t/how-to-find-if-a-method-is-implemented-for-an-interface/636)._
