# Type matching with positional vs keyword arguments

**URL:** https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854
**Category:** General Usage
**Tags:** question, parametric-types
**Created:** [January 20, 2019, 10:32pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854 "2019-01-20T22:32:39Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 20, 2019, 10:32pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/1 "2019-01-20T22:32:39Z")

</div>

Hi there, can anyone explain why the different behavior in the following two definitions? Note that in the first case all arguments are positional, whereas in the second case `b` is a keyword argument:

```julia
julia> f(a::C, b::R=R(1)) where {R <: Real, C <: Union{R, Complex{R}}} = b*a
f (generic function with 2 methods)

julia> f(2.0, 3.0)
6.0

```

vs

```julia
julia> f(a::C; b::R=R(1)) where {R <: Real, C <: Union{R, Complex{R}}} = b*a
ERROR: UndefVarError: R not defined
Stacktrace:
 [1] top-level scope at none:0

```

Thank you!

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [January 20, 2019, 10:54pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/2 "2019-01-20T22:54:15Z")

</div>

Keyword arguments don’t participate in dispatch. So what you’ve done here is the equivalent of this:

```julia
f(a::C; b=R(1)) where {R <: Real, C <: Union{R, Complex{R}}} = b*a

```

No value for `R` can be determined by dispatch, so it’s undefined which means `R(1)` will fail.

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 20, 2019, 11:02pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/3 "2019-01-20T23:02:37Z")

</div>

That makes a lot of sense, thank you. Note to self: this is explained [here](https://docs.julialang.org/en/v1/manual/methods/#Note-on-Optional-and-keyword-Arguments-1).

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 20, 2019, 11:32pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/4 "2019-01-20T23:32:16Z")

</div>

Wait a sec: `R` is determined by dispatch in this other example however

```julia
julia> f(a::C) where {R <: Real, C <: Union{R, Complex{R}}} = println(R)
f (generic function with 1 method)

julia> f(Float64(3))
Float64

julia> f(Float32(3)+Float32(2)im)
Float32

```

How come having an additional keyword argument breaks this? From what I understand from [here](https://docs.julialang.org/en/v1/manual/methods/#Note-on-Optional-and-keyword-Arguments-1), dispatch occurs, `R` and `C` are matched against concrete types, and _then_ keyword arguments are processed. By then, `R` should have a concrete type associated.

I’m probably missing something.

---

<div class="post-metadata">

### Author: ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)
#### Post date: [January 21, 2019, 3:40am UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/5 "2019-01-21T03:40:54Z")

</div>

It seems that you hit an interesting corner case.

Consider the following

```julia
julia> f(a::C; b::R) where {R <: Real, C <: Union{R, Complex{R}}} = b*a
ERROR: UndefVarError: R not defined

```

It seems that the `where` clause is only applied to the positional arguments. Therefore the type `R` is not known when the keyword arguments are being processed.

At the other hand

```julia
julia> g(a::C, x::R=2; b::R=R(3)) where {R <: Real, C <: Union{R, Complex{R}}} = b*a
g (generic function with 2 methods)

julia> g(5)
15

```

Type `R` is now directly referenced by one of the positional arguments and that seems to make it OK to also use type `R` for one of the keyword arguments.

By the way, the following works too. No need to assign a default value to the last positional argument.

```julia
julia> h(a::C, x::R; b::R=R(3)) where {R <: Real, C <: Union{R, Complex{R}}} = b*a
g (generic function with 2 methods)

julia> h(5, 2)
15

```

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 21, 2019, 6:12am UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/6 "2019-01-21T06:12:51Z")

</div>

> [@jandehaan](#):
>
> It seems that the `where` clause is only applied to the positional arguments. Therefore the type `R` is not known when the keyword arguments are being processed.

Yes, although that doesn’t explain why the example in my last post works: `R` there does not appear explicitly in any positional arguments, it does only implicitly in the `where` clause for `C`.

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 21, 2019, 4:41pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/7 "2019-01-21T16:41:56Z")

</div>

To update this discussion with an even more minimal example, since I’m still not convinced by this:

Why does the following work

```julia
julia> f(a::C) where {R <: Real, C <: Union{R, Complex{R}}} = println(R)
f (generic function with 1 method)

julia> f(Float64(3))
Float64

julia> f(Float32(3)+Float32(2)im)
Float32

```

but the following doesn’t?

```julia
julia> g(a::C; b=R(1)) where {R <: Real, C <: Union{R, Complex{R}}} = println(R)
ERROR: UndefVarError: R not defined
Stacktrace:
 [1] top-level scope at none:0

```

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [January 21, 2019, 5:10pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/8 "2019-01-21T17:10:35Z")

</div>

This may be a bug; I’ve invited @jeff.bezanson to chime in. It has to do with the order of evaluation and scoping of type parameters.

---

<div class="post-metadata">

### Author: ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)
#### Post date: [January 21, 2019, 10:55pm UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/9 "2019-01-21T22:55:16Z")

</div>

Yes, I think this can be fixed. This is a holdover from pre-0.7, when the dispatch rules said that all static parameters must have well-determined values for a method to match. If you have that rule, but some static parameters are only referenced by keyword argument types, then it would be impossible to call the method without keyword arguments, which is not what you usually want!

To work around that, the front-end tries to separate static parameters used by positional arguments from those used by keyword arguments. That allows simple cases like this to work:

```julia
function f(x::X; y::Y) where {X, Y}

```

but clearly doesn’t work if one variable occurs in the other’s bounds. So this can now be fixed by simply letting both positional and keyword methods use the same set of static parameters.

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [January 22, 2019, 6:32am UTC](https://discourse.julialang.org/t/type-matching-with-positional-vs-keyword-arguments/19854/10 "2019-01-22T06:32:12Z")

</div>

Thanks for the explanation. I opened an issue to track this: [Keyword arguments parametric types break matching · Issue #30792 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/30792)
