# How do I tell if an object is callable (a function-like object)?

**URL:** <https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831>\
**Category:** General Usage\
**Tags:** question, functors\
**Created:** [June 26, 2023, 6:07am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831 "2023-06-26T06:07:40Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![coldinjection](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/coldinjection/32/51061_2.png) [@coldinjection](https://discourse.julialang.org/u/coldinjection)\
**Post date:** [June 26, 2023, 6:07am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/1 "2023-06-26T06:07:40Z")

</div>

Say there’s a type T, how can I tell if function (t::T)()… is defined?  
Is there any way other than trying t() and catching a MethodError?

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [June 26, 2023, 6:11am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/2 "2023-06-26T06:11:26Z")

</div>

maybe using `methods`?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 26, 2023, 6:18am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/3 "2023-06-26T06:18:52Z")

</div>

Trying and catching is, unfortunately, the easiest/surefire way. Checking `methods` is tricky, and if you need to check, using `applicable` with a specific signature is better (though not by much).

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 26, 2023, 8:16am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/4 "2023-06-26T08:16:01Z")

</div>

Maybe you could define an abstract type and have the callable types subtype it?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 26, 2023, 10:33am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/5 "2023-06-26T10:33:41Z")

</div>

> [@Sukera](#):
>
> Checking `methods` is tricky

Could you elaborate on the issues that might arise using `methods` or `hasmethod`/`applicable`?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 26, 2023, 11:27am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/6 "2023-06-26T11:27:34Z")

</div>

> [@Benny](#):
>
> Could you elaborate on the issues that might arise using `methods` or `hasmethod`/`applicable`?

Because you need an instance of the object to determine it - the type is not enough. The methods are attached to “objects of type `T`”, not to the type object `T`.

The issues I’m referring to are potential confusion about what `methods`/`applicable` tells you:

```julia
julia> struct Foo{T} end

julia> (f::Foo{T} where T <: Integer)() = 1

julia> methods(Foo{Int})
# 1 method for type constructor:
 [1] (var"#ctor-self#"::Type{Foo{T}} where T)()
     @ REPL[3]:1

julia> applicable(Foo{Int})
true

```

All good, right? Not so fast, calling that is the _constructor method_ for `Foo` (as the printout for `methods` suggests):

```julia
julia> Foo{Int}()
Foo{Int64}()

```

and only if we pass in an instance (which we could then just call anyway) do we get out the `1`:

```julia
julia> methods(Foo{Int}())
# 1 method for callable object:
 [1] (f::Foo{T} where T<:Integer)()
     @ Main REPL[4]:1

julia> applicable(Foo{Int}())
true

julia> Foo{Int}()()
1

```

The reason I’m recommending `applicable` over inspecting `methods` is that there are situations where throwing isn’t really a good option either, where it’s safer to have actual arguments you’ll try to pass that you want to check.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 26, 2023, 11:40am UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/7 "2023-06-26T11:40:02Z")

</div>

Needing an instance `t` to check for methods `(t::T)(args...`) is probably rooted in `methods`/`hasmethod`/`applicable` and a whole lot of other functions being intended for generic functions, where it is easy to find the instance. Might be a pain to type `typeof(foo)` and `Type{T}` instead, but it’d be nice if those functions took the type instead of the callable instance.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 26, 2023, 12:15pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/8 "2023-06-26T12:15:24Z")

</div>

Note that `Function` is an abstract type, so you are free to declare `struct Foo <: Function`. (Not all callable types do this, however.)

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 26, 2023, 2:18pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/9 "2023-06-26T14:18:09Z")

</div>

> [@Benny](#):
>
> Might be a pain to type `typeof(foo)` and `Type{T}` instead, but it’d be nice if those functions took the type instead of the callable instance.

That wouldn’t solve the issue though; the type of an instance would give you its type, `methods` on which just gives you the constructor, as above. What then is the type of `typeof(Int)`?

What’s leaking here is that julia doesn’t really have higher kinded/dependent types - julia answers the above question by saying `typeof(DataType) == DataType`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 26, 2023, 2:58pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/10 "2023-06-26T14:58:18Z")

</div>

> [@Sukera](#):
>
> Because you need an instance of the object to determine it - the type is not enough. The methods are attached to “objects of type `T`”, not to the type object `T`.

Note that this is just a user facing API problem, not a fundamental problem.

```julia
julia> struct Foo{T} end

julia> (f::Foo{T} where T <: Integer)() = 1;

julia> Core.Compiler._methods_by_ftype(Tuple{Foo{Int}}, -1, typemax(UInt))
1-element Vector{Any}:
 Core.MethodMatch(Tuple{Foo{Int64}}, svec(), (f::Foo{T} where T<:Integer)() @ Main REPL[22]:1, true)

```

> [@Sukera](#):
>
> That wouldn’t solve the issue though; the type of an instance would give you its type, `methods` on which just gives you the constructor, as above. What then is the type of `typeof(Int)`?
> 
> What’s leaking here is that julia doesn’t really have higher kinded/dependent types - julia answers the above question by saying `typeof(DataType) == DataType`.

`methods` and `applicable` take instances of the type, but the compiler itself operates on the type level. We tell the difference between `(::T)(x)` and `T(x)` by distinguishing between `Tuple{T, typeof(x)}` and `Tuple{Type{T}, typeof(x)}`:

```julia
julia> Core.Compiler._methods_by_ftype(Tuple{Type{Foo{Int}}}, -1, typemax(UInt))
1-element Vector{Any}:
 Core.MethodMatch(Tuple{Type{Foo{Int64}}}, svec(), (var"#ctor-self#"::Type{Foo{T}} where T)() @ Main REPL[21]:1, true)

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 26, 2023, 3:41pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/11 "2023-06-26T15:41:52Z")

</div>

> [@Mason](#):
>
> Note that this is just a user facing API problem, not a fundamental problem.

I’m using the user-facing API, because that is much more reliable when it comes to talking about what people can actually use. I can’t reproduce this on a more recent commit of julia:

```julia
julia> struct Foo{T} end

julia> (f::Foo{T} where T <: Integer)() = 1;

julia> Core.Compiler._methods_by_ftype(Tuple{Foo{Int}}, -1, typemax(UInt))

julia> Core.Compiler._methods_by_ftype(Tuple{Type{Foo{Int}}}, -1, typemax(UInt))

julia> versioninfo()
Julia Version 1.10.0-DEV.1525
Commit 0da46e25c86 (2023-06-20 02:23 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: 24 × AMD Ryzen 9 7900X 12-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, znver3)
  Threads: 34 on 24 virtual cores
Environment:
  JULIA_PKG_USE_CLI_GIT = true

```

You may say that it’s just a user-facing API problem, but that really just hides the underlying issue of `typeof(typeof(Int)) == typeof(Int)` being `DataType == DataType`.

EDIT: took a while to find, but the reference about “what is the type of `DataType`?” I had in mind was [type universe in nLab](https://ncatlab.org/nlab/show/type+universe)

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [June 26, 2023, 3:47pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/12 "2023-06-26T15:47:30Z")

</div>

If the reason you are avoiding catching MethodError is for speed, you could see this thread:: [Performance of hasmethod vs try-catch on MethodError](https://discourse.julialang.org/t/performance-of-hasmethod-vs-try-catch-on-methoderror/99827).

The solution is overkill (works by caching the `MethodError`s) but it works, is type stable, and only faces a ~10 ns overhead.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 26, 2023, 3:52pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/13 "2023-06-26T15:52:51Z")

</div>

> [@Sukera](#):
>
> I’m using the user-facing API, because that is much more reliable when it comes to talking about what people can actually use. I can’t reproduce this on a more recent commit of julia:

I’m not at all suggesting people reach into the internals for this, I’m just giving some more context for what specifically is missing here, which is not some fundamental problem that requires changing the type system but some missing methods / functions.

> [@Sukera](#):
>
> You may say that it’s just a user-facing API problem, but that really just hides the underlying issue of `typeof(typeof(Int)) == typeof(Int)` being `DataType == DataType`.

Again though, that underlying issue isn’t fundamental but about APIs. The entire reason `Type` exists, because it’s exactly meant to be the type of types:

```julia
julia> Int isa Type{Int}
true

```

I definitely agree that it’s annoying that `typeof(Int)` gives `DataType` though, because we’re all used to using `typeof` for data. But it is a further API issue that we don’t expose `Core.Typeof` instead of `typeof`

```julia
julia> Core.Typeof(1)
Int64

julia> Core.Typeof(Int)
Type{Int64}

```

* * *

At the end of the day though, yes I agree if all you have is `T` it’s very hard to find out if there are methods on instances of `T`, I’m just pointing out that these aren’t core problems with the type hierarchy or whatever, but problems which how APIs are set up.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 26, 2023, 4:03pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/14 "2023-06-26T16:03:27Z")

</div>

No, I’m specifically talking about `typeof`, because that’s what the user-facing, stable API _is_, and what the julia type lattice consists of. `Core.Typeof` can do whatever it wants to; it’s internal. From the user perspective, changing `typeof` to match `Core.Typeof` (while allowing such nested type shenanigans), is a big change, and exactly something that would be required to soundly talk about doing such queries in user code.

If you need internals to even access this kind of type computation, it’s not at all something that the (user facing) type system (i.e., the lattice spanned by `<:` on `typeof` of objects) can “do” (even if the underlying computation can be done). If you change `typeof` to `Core.Typeof` you can do pretty much whatever you want, because it’s a different lattice with different objects on that lattice, due to `Core.Typeof` giving a much bigger set of possible types/objects.

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [June 26, 2023, 4:36pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/15 "2023-06-26T16:36:47Z")

</div>

Note that there is already `Base.Callable` defined in essentials.jl to be the union of `Function` and `Type`. It is used to guide multiple dispatch for methods like `get!` in dict.jl.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 26, 2023, 9:34pm UTC](https://discourse.julialang.org/t/how-do-i-tell-if-an-object-is-callable-a-function-like-object/100831/16 "2023-06-26T21:34:49Z")

</div>

> [@Sukera](#):
>
> the underlying issue of `typeof(typeof(Int)) == typeof(Int)` being `DataType == DataType`

Is that really a problem for figuring out if a given type’s instances are callable? Here’s the three cases I can think of:

1. generic function: providing `typeof(foo)` is as specific as `foo` itself, being a singleton type
2. constructor: we can provide `Type{T}` manually, and a method can extract the `T` from an argument `::Type{Type{T}}` and then do what the existing methods do.
3. all other callable instances: providing `T` is sufficient for finding a method `(t::T)(args...)`. If we provide an instance `t`, the instance values are just ignored.

We don’t need to implement (1) and (2) because the callables of interest are accessible, but a new method that does (3) and also happens to handle (1) and (2) seems feasible. An issue for (2) though, `@nospecialize` can’t do unnamed arguments, and it doesn’t seem like `@nospecialize(r::Type{R})` prevents specialization, based on `(@which ...).specializations`.
