'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 |