# Should I add type annotation to keyword arguments?

**URL:** <https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231>\
**Category:** Performance\
**Tags:** keyword-arguments\
**Created:** [May 22, 2023, 3:37pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231 "2023-05-22T15:37:07Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [May 22, 2023, 3:37pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/1 "2023-05-22T15:37:07Z")

</div>

Old versions of Julia’s performance tips  
[https://docs.julialang.org/en/v1/manual/performance-tips](https://docs.julialang.org/en/v1/manual/performance-tips)  
advised annotating the types of keyword arguments, but this is no longer mentioned in the current version. Do I still need to pay attention to keyword arguments in terms of performance, e.g function call overhead and compiler specialization?

---

<div class="post-metadata">

**Author:** ![Tarny\_GG\_Channie](https://avatars.discourse-cdn.com/v4/letter/t/3bc359/32.png) [@Tarny\_GG\_Channie](https://discourse.julialang.org/u/Tarny_GG_Channie)\
**Post date:** [May 23, 2023, 4:55am UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/2 "2023-05-23T04:55:03Z")

</div>

As a rule of thumb, Julia performance is similar to if all the types of the arguments are known. Not specializing is IMHO just an optimization.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [May 23, 2023, 5:38am UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/3 "2023-05-23T05:38:06Z")

</div>

I guess knowing the type might make a difference in certain cases, although whether this matters in real code is less clear.

```julia
julia> using BenchmarkTools

julia> d = Any[1]
1-element Vector{Any}:
 1

julia> f(; d, e = d[1]) = e + 1
f (generic function with 1 method)

julia> @btime f(; d = $d);
  22.575 ns (0 allocations: 0 bytes)

julia> g(; d, e::Int = d[1]) = e + 1
g (generic function with 1 method)

julia> @btime g(; d = $d);
  6.634 ns (0 allocations: 0 bytes)

```

I would refrain from type-annotations unless benchmarks suggested otherwise.

---

<div class="post-metadata">

**Author:** ![Tarny\_GG\_Channie](https://avatars.discourse-cdn.com/v4/letter/t/3bc359/32.png) [@Tarny\_GG\_Channie](https://discourse.julialang.org/u/Tarny_GG_Channie)\
**Post date:** [May 23, 2023, 6:23am UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/4 "2023-05-23T06:23:10Z")

</div>

Yeah… there are some weird cases.

---

<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:** [May 23, 2023, 5:16pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/5 "2023-05-23T17:16:04Z")

</div>

By the way does anyone have a source for the folk tale “Julia specializes on kwargs but does not dispatch on them”? I think I read it from @oxinabox but the trail runs cold after that

I guess it’s fairly easy to demonstrate in practice but I couldn’t find it in the official docs

```julia
julia> g(; x) = zero(x)
g (generic function with 1 method)

julia> @code_warntype g(; x=1)
MethodInstance for Core.kwcall(::NamedTuple{(:x,), Tuple{Int64}}, ::typeof(g))
  from kwcall(::Any, ::typeof(g)) @ Main REPL[9]:1
Arguments
  _::Core.Const(Core.kwcall)
  @_2::NamedTuple{(:x,), Tuple{Int64}}
  @_3::Core.Const(g)
Locals
  @_4::Int64
  x::Int64
Body::Int64 # correct inference
...

```

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [May 23, 2023, 5:31pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/6 "2023-05-23T17:31:10Z")

</div>

It is documented in [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#Note-on-Optional-and-keyword-Arguments), but it’s one paragraph in the middle of a pretty long page. Maybe some emphasis or hoisting of the admonition to a more prominent location would help?

---

<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:** [May 23, 2023, 9:18pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/7 "2023-05-23T21:18:41Z")

</div>

Yeah I had that part in mind:

> Keyword arguments behave quite differently from ordinary positional arguments. In particular, they do not participate in method dispatch. Methods are dispatched based only on positional arguments, with keyword arguments processed after the matching method is identified.

I was actually wondering where it says that methods are still _specialized_ on kwargs, even though they play no part in dispatch

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [May 23, 2023, 9:38pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/8 "2023-05-23T21:38:31Z")

</div>

I see. In a sense it’s covered by omission in [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing). Perhaps the follow-up question is why specialization is so often thought to be near 1-1 with dispatch. Maybe it isn’t and I’m overgeneralizing from a small sample size!

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [May 24, 2023, 6:20am UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/9 "2023-05-24T06:20:19Z")

</div>

Its only notable because Julia never used to specialize on kwargs.

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [May 25, 2023, 5:26pm UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/10 "2023-05-25T17:26:26Z")

</div>

Now that I did not know. Is there some background on why and/or when the switch was made? It seems like people would’ve avoided kwargs like the plague if they weren’t specialized because of dynamic dispatch, or was that not a problem?

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [May 30, 2023, 1:32am UTC](https://discourse.julialang.org/t/should-i-add-type-annotation-to-keyword-arguments/99231/11 "2023-05-30T01:32:17Z")

</div>

It isn’t in HISTORY.md, I guess considered an implementation detail or just forgotten

I know it was after the original MLDataUtils, MLDataPattern etc was written (which was 2017ish) as IIRC that constrains lots of keyword arguments for convenience but positional for performance. (It also massively overused types because no constant folding)

@ChrisRackauckas might know as DiffEqverse was a big winner in that one.
