# Should function-like objects be subtypes of Function?

**URL:** <https://discourse.julialang.org/t/should-function-like-objects-be-subtypes-of-function/107081>\
**Category:** General Usage\
**Tags:** question, functors\
**Created:** [December 3, 2023, 7:11pm UTC](https://discourse.julialang.org/t/should-function-like-objects-be-subtypes-of-function/107081 "2023-12-03T19:11:43Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [December 3, 2023, 7:11pm UTC](https://discourse.julialang.org/t/should-function-like-objects-be-subtypes-of-function/107081/1 "2023-12-03T19:11:43Z")

</div>

For a [function-like object](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects), aka callable/functor, is there any problem with making it a subtype of `Function`?

As in,

```julia
struct Polynomial{R} <: Function # XXX
    coeffs::Vector{R}
end

(p::Polynomial)(t) = evaluate_polynomial(p, t) # see code in Julia docs

```

The point of this would be to be able to pass a `Polynomial` object as a `Function` argument, for example as the argument `control` in a function [`discretize`](https://github.com/JuliaQuantumControl/QuantumPropagators.jl/blob/e62fce490feb4138fbd8dd61a7585d665e32554b/src/controls.jl#L41-L66) defined as (among other methods)

```julia
function discretize(control::Function, tlist)
    return [control(t) for t in tlist]
end

```

Of course, I’m not saying that _all_ callables must/should be subtypes of `Function`, but if they’re not subtypes of some other abstract type, is there a reason not to make them subtypes of `Function`?

---

<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:** [December 3, 2023, 7:58pm UTC](https://discourse.julialang.org/t/should-function-like-objects-be-subtypes-of-function/107081/2 "2023-12-03T19:58:23Z")

</div>

One difference it can make is that subtypes of `Function` will not be automatically specialized by methods that pass it with the `::Function` or `::Any` annotation and do not call it even after inlining passes.\* Of course if you want your callables to act more in line with `Function`’s design to limit overcompilation, then subtype it; that’s probably a good idea if a program has many functors passing through many call chains.

\*Example:

```julia
julia> bar(op, a, b) = op(a, b);

julia> foo(op, a, b) = @noinline bar(op, a, b);

julia> foo(op::typeof(+), a, b) = @noinline bar(op, a, b);

julia> struct Minus end; (::Minus)(a, b) = a-b

julia> foo(-, 1, 1), foo(Minus(), 1, 1), foo(+, 1, 1)
(0, 0, 2)

julia> @which(foo(-, 1, 1))
foo(op, a, b) in Main at REPL[40]:1

julia> @which(foo(-, 1, 1)).specializations # Minus specializes, - does not
svec(MethodInstance for foo(::Function, ::Int64, ::Int64), MethodInstance for foo(::Minus, ::Int64, ::Int64), nothing, nothing, nothing, nothing, nothing, nothing)

julia> @which(foo(+, 1, 1))
foo(op::typeof(+), a, b) in Main at REPL[41]:1

julia> @which(foo(+, 1, 1)).specializations
svec(MethodInstance for foo(::typeof(+), ::Int64, ::Int64), nothing, nothing, nothing, nothing, nothing, nothing, nothing)

```
