9

In Julia, what's the best way to determine whether an object is callable? (E.g. is there an analog of python's callable function?)

EDIT: Here's what one could wish for:

f() = println("Hi")
x = [1,2,3]
a = 'A'

callable(f)    # => true
callable(x)    # => false
callable(a)    # => false
callable(sin)  # => true
Yly
  • 2,150
  • 4
  • 20
  • 33
  • are you looking for `method_exists`? – Gnimuc Jan 15 '17 at 07:29
  • @Gnimuc I just tried that, but it doesn't have quite the functionality I'm looking for. I edited the post to show what I would like (essentially something like Python's `callable`), but perhaps such a feature does not exist (yet) in Julia... – Yly Jan 15 '17 at 08:33
  • 1
    there is a `Function` type in julia, `typeof(x) <: Function` works well with your examples. – Gnimuc Jan 15 '17 at 08:41
  • @Gnimuc That seems like a pretty good solution, and will work for the use case I have in mind. I'll accept it if you post it as an answer. (However, I don't think it works generically, since any object can potentially be callable (not just function types). For example, constructors apparently fail this test of callability.) – Yly Jan 15 '17 at 08:49
  • good point. I also hope someone could elaborate more on this topic. – Gnimuc Jan 15 '17 at 08:58

2 Answers2

5

iscallable(f) = !isempty(methods(f))

This is the method used in Base (see here).

But consider rethinking your problem. Custom dispatch like this will probably be slow.

giordano
  • 8,087
  • 3
  • 23
  • 48
Isaiah Norton
  • 4,205
  • 1
  • 24
  • 38
  • 2
    `x = [1]; (x::Vector{T}){T}() = x; x(); iscallable(x)`. Does just `iscallable(f) = !isempty(methods(f))` work? – David P. Sanders Jan 15 '17 at 23:38
  • @DavidP.Sanders, as of julia 1.8, `iscallable(f) = !isempty(methods(f))` works with `y = [1]; (y::Vector{T})() where {T} = y; y(); iscallable(y)`. – Nathan Musoke Apr 17 '23 at 18:24
1

How about this:

julia> function iscallable(f)
       try
           f()
           return true

       catch MethodError
           return false
       end
end
iscallable (generic function with 1 method)


julia> f() = 3
f (generic function with 1 method)

julia> iscallable(f)
true

julia> x = [1,2]
2-element Array{Int64,1}:
 1
 2

julia> iscallable(x)
false

This is actually quite a Pythonic thing to do (and I suspect not very efficient). What's the use case?

David P. Sanders
  • 5,210
  • 1
  • 23
  • 23