# Is it safe to dispatch on function types?

**URL:** <https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [October 15, 2018, 2:26pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346 "2018-10-15T14:26:51Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [October 15, 2018, 2:26pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/1 "2018-10-15T14:26:51Z")

</div>

Let’s say I have a generic function,

```julia
test(f, a) = f(a)

```

where `f` is a _function_ and `a` some number.

I want to dispatch on the function argument `f`. Specifically, do something like

```julia
test(f::typeof(cos), a) = "haha!"

```

I am using Julia 1.0 and this works.

```julia
julia> test(sin, 1)
0.8414709848078965

julia> test(cos, 1)
"haha!"

```

But I am worried whether it is (a) safe and (b) has some gotchas.

I couldn’t find something about it at the docs, if I missed it please let me know.

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [October 15, 2018, 2:30pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/2 "2018-10-15T14:30:55Z")

</div>

Yup, perfectly safe. It is not uncommon for me to do this (I go pretty crazy with multiple dispatch).

It’s funny, Julia isn’t object oriented, but another way of looking at it is that everything is an object. You can add methods to functions, so in a sense every function in Julia is a [“functor”](https://en.wikipedia.org/wiki/Function_object) (this is a common but clearly incorrect use of the word, the true definition is [here](https://en.wikipedia.org/wiki/Functor)).

Almost forgot, the one caveat I’d give is that you should only do this on named functions that appear in the global scope of your package. I’m not sure whether it’s possible to do this with functions for which this is not true, but if it is, I’d imagine there are probably lots of “gotchas”.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [October 15, 2018, 2:45pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/3 "2018-10-15T14:45:49Z")

</div>

It’s actually also used in Base for optimizations, when for a specific function a general operation can be optimized. For example this was done [here](https://github.com/JuliaLang/julia/pull/27188) for `reduce(hcat, v)` where `v` is a vector of vectors. Naively this would keep reallocating the result of each `hcat`, but now Julia overloads this signature to make it efficient:

```julia
julia> v = [rand(1_000) for _ in 1:1000];

julia> function f1(v)
           h = reshape(v[1], :, 1)
           for i in 2:length(v)
               h = hcat(h, v[i])
           end
           h
       end
f1 (generic function with 1 method)

julia> f2(v) = reduce(hcat, v)
f2 (generic function with 1 method)

julia> @benchmark f1($v)
BenchmarkTools.Trial: 
  memory estimate: 3.73 GiB
  allocs estimate: 2998
  --------------
  minimum time: 318.887 ms (9.31% GC)
  median time: 337.090 ms (9.61% GC)
  mean time: 338.537 ms (11.05% GC)
  maximum time: 419.100 ms (27.04% GC)
  --------------
  samples: 15
  evals/sample: 1

julia> @benchmark f2($v)
BenchmarkTools.Trial: 
  memory estimate: 7.63 MiB
  allocs estimate: 2
  --------------
  minimum time: 700.406 μs (0.00% GC)
  median time: 756.052 μs (0.00% GC)
  mean time: 839.459 μs (10.05% GC)
  maximum time: 40.769 ms (93.56% GC)
  --------------
  samples: 5912
  evals/sample: 1

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [October 15, 2018, 2:58pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/4 "2018-10-15T14:58:54Z")

</div>

> [@Datseris](#):
>
> test(f::typeof(cos), a) = “haha!”

The above would work even if `cos` was an anonymous function.

---

<div class="post-metadata">

**Author:** ![simonschoelly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonschoelly/32/21606_2.png) [@simonschoelly](https://discourse.julialang.org/u/simonschoelly)\
**Post date:** [October 15, 2018, 4:38pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/5 "2018-10-15T16:38:39Z")

</div>

So if I see that correctly, Julia does dispatch on function types but not on the individual methods that belong to that function?

And Julia usually compiles a different method for each combinations of argument types that are passed to a function. Does it also do that, when you pass a function to a function?

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [October 15, 2018, 4:39pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/6 "2018-10-15T16:39:47Z")

</div>

> [@simonschoelly](#):
>
> Does it also do that, when you pass a function to a function?

yes

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [October 15, 2018, 4:52pm UTC](https://discourse.julialang.org/t/is-it-safe-to-dispatch-on-function-types/16346/7 "2018-10-15T16:52:13Z")

</div>

> [@simonschoelly](#):
>
> And Julia usually compiles a different method for each combinations of argument types that are passed to a function. Does it also do that, when you pass a function to a function?

Be careful about that. Sometimes julia saves compile time by not specializing on function arguments. This is a good heuristic but can come to bite you and is hard to debug. Last paragraph:

> <https://github.com/JuliaLang/julia/blob/master/doc/src/devdocs/functions.md>
