# Can callable structs subtype Function? Should they?

**URL:** <https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909>\
**Category:** General Usage\
**Tags:** function\
**Created:** [October 29, 2024, 9:22am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909 "2024-10-29T09:22:59Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [October 29, 2024, 9:22am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/1 "2024-10-29T09:22:59Z")

</div>

The docstring of `Function` doesn’t specify any constraints on subtypes, so I’m wondering whether it makes sense to define callable structs (functors) as `<: Function`.

---

<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:** [October 29, 2024, 9:35am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/2 "2024-10-29T09:35:29Z")

</div>

As far as I remember, the general rule was “no”, because there’s some additional requirements for `Function` that are not really documented. It’s not just being callable.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [October 29, 2024, 10:02am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/3 "2024-10-29T10:02:33Z")

</div>

I was thinking maybe every `Function` should have its own singleton subtype `typeof(f)`, but that’s not written anywhere for instance.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [October 29, 2024, 10:33am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/4 "2024-10-29T10:33:44Z")

</div>

> [Should callable structs (functors) subtype `Function`?](https://discourse.julialang.org/t/should-callable-structs-functors-subtype-function/121909)

I think not. A callable structs might want to inherit from something else instead, right ?

> [@Sukera](#):
>
> some additional requirements for `Function` that are not really documented

I’d be curious to know what these are.

---

<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:** [October 29, 2024, 10:37am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/5 "2024-10-29T10:37:07Z")

</div>

> [@gdalle](#):
>
> I was thinking maybe every `Function` should have its own singleton subtype `typeof(f)`, but that’s not written anywhere for instance.

Nope, closures are not singletons and are subtypes of `Function`:

```julia
julia> f = let x = 1
           () -> x + 1
       end
#1 (generic function with 1 method)

julia> supertype(typeof(f))
Function

julia> Base.issingletontype(typeof(f))
false

```

FWIW I think if your struct is mainly used “like” a function, and there’s not another abstract type that makes more sense for you to inherit from, it can make sense to make it a `<:Function` because sometimes people write type signatures like

```julia
function higher_order(f::Function)
    ...
end

```

This isn’t so common, but it does unfortunately happen so you can bypass it by subtyping function, but honestly it’s not a big deal either way IMO.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [October 29, 2024, 10:39am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/6 "2024-10-29T10:39:07Z")

</div>

> [@e3c6](#):
>
> I think not. A callable structs might want to inherit from something else instead, right ?

That’s true, I adjusted the title to better reflect my question.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 29, 2024, 11:07am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/7 "2024-10-29T11:07:32Z")

</div>

As a datapoing – Accessors.jl, a popular package which primary functionality is the creation of “fancy callables”, **does not** subtype `Function` for performance reasons. [See a discussion](https://github.com/JuliaObjects/Accessors.jl/issues/37) there.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [October 29, 2024, 11:25am UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/8 "2024-10-29T11:25:26Z")

</div>

> [@aplavin](#):
>
> **does not** subtype `Function` for performance reasons

Interesting! For future reference, this is because Julia [doesn’t specialize on `Function` arguments by default](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing).

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [October 29, 2024, 1:29pm UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/9 "2024-10-29T13:29:16Z")

</div>

Pedant: Julia specializes on function args when they’re explicitly called in the function body. If folks are going to treat it like a normal function, then having it optimize like a normal function is a feature, I think. The only trouble is if it plays some sort of double-duty — for example, dispatching on `:` has thrown me for a loop so many times it’s embarrassing.

It is really common — there are [hundreds of `Function` subtypes](https://juliahub.com/ui/Search?type=code&q=(%5Cbstruct%5Cb%7C%5Cbtype%5Cb).*%3C:%5Cs*Function%5Cs*$&rx=true) in the ecosystem. I’m not aware of any “interface” requirements beyond the callable method.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [October 29, 2024, 8:25pm UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/10 "2024-10-29T20:25:01Z")

</div>

> [@mbauman](#):
>
> for example, dispatching on `:` has thrown me for a loop so many times it’s embarrassing.

What do you mean?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [October 29, 2024, 8:36pm UTC](https://discourse.julialang.org/t/can-callable-structs-subtype-function-should-they/121909/11 "2024-10-29T20:36:02Z")

</div>

Here’s an example:

> <https://github.com/JuliaStats/Statistics.jl/pull/38>
>
> Ensures we get the specialization we want when passing \`dims=(:)\`. Fixes #37.

`:` does double-duty: it’s a function to create ranges but it’s also — by itself — used as a flag for slicing. In the latter usage, you don’t call it like a function so it might not specialize and can lead to unexpected performance snags.
