'How do I check if a method exists for a particular type?

LATEST UPDATE: Shep has provided an answer that updates this question to v1+.

UPDATE: Thanks to @rickhg12s for pointing out that it appears I may have stumbled upon a bug. method_exists(<, (MyType, MyType)) is returning true while method_exists(isless, (MyType, MyType)) is returning false. I'm on v0.3.x but @rickhg12s is on the nightly build of v0.4, so I'll file an issue.

How do I check if a method exists for a particular type?

I thought I could do this using, for example:

method_exists(<, (Int, Int))

which will return true since the less than comparison is defined for two integers. However, when I define my own type:

type MyType; end

and then try:

method_exists(<, (MyType, MyType))

it returns true. But I thought that it would return false, since:

a = MyType()
a < a

throws an error since < is not defined for MyType. So how can I detect at run-time whether a method for a given type exists?



Solution 1:[1]

It turns out that method_exists is (currently) the best way to check whether a method exists for a particular type, but one needs to be very careful. My example above just happened to stumble upon some slightly confusing (but internally consistent) behaviour in Julia's inner workings. Read on if you're still interested.

@rickhg12s pointed out in the comments to the question that method_exists(<, (MyType, MyType)) is returning true while method_exists(isless, (MyType, MyType)) is returning false.

Sounds like a bug right? I filed an issue and the julia devs confirmed that the behaviour observed, while admittedly confusing, is internally consistent.

< and isless are two different methods. Importantly, < has default behaviour for the case where no explicit method for < has been defined. That behaviour is to pass the arguments on to the isless function. The consequence of this behaviour is that < is implicitly defined for every type, even brand new ones that have just been created. So method_exists(<, (MyType, MyType)) should return true. isless on the other hand, is the "lowest" in the chain - there is no other function it can pass things onto, so if isless has not been explicitly extended to the new type, Julia returns an error if you try to use it, and method_exists(isless, (MyType, MyType)) will correctly return false.

Now that it has been pointed out to me, I can see the logic behind this. But the implication is that users of method_exists need to be careful that they're applying it to the function that is "lowest" in the chain.

Solution 2:[2]

If you want to stick to Base functions you can use hasmethod.

hasmethod(<, Tuple{Int, Int}) # true

abstract type MyType end

hasmethod(isless, Tuple{MyType, MyType}) # false

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Colin T Bowers
Solution 2 Shep Bryan