# I'm confused about methods

**URL:** <https://discourse.julialang.org/t/im-confused-about-methods/48508>\
**Category:** General Usage\
**Created:** [October 16, 2020, 6:42pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508 "2020-10-16T18:42:06Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 6:42pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/1 "2020-10-16T18:42:07Z")

</div>

This surprises me (particularly the part where `f()` evaluates to `1`):

```julia
julia> begin
           f(a)=2
           f(a,b)=3
           f(;a,b)=4
           f()=1
       end
f (generic function with 3 methods)

julia> methods(f)
# 3 methods for generic function "f":
[1] f(; a, b) in Main at REPL[1]:5
[2] f(a) in Main at REPL[1]:2
[3] f(a, b) in Main at REPL[1]:3

julia> f()
1

julia> f(1)
2

julia> f(1,2)
3

julia> f(a=1,b=2)
4

julia>

```

For fun, repeat with the `f()=1` moved to the top of the list.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [October 16, 2020, 7:00pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/2 "2020-10-16T19:00:25Z")

</div>

Why does it surprise you? What did you expect `f()` to give and why?

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 7:22pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/3 "2020-10-16T19:22:27Z")

</div>

Notice that `f()` doesn’t appear in the return from `methods()`. On the other hand, if I never define `f(; a,b)` then `methods(f)` gives

```julia
# 3 methods for generic function "f":
[1] f() in Main at REPL[1]:1
[2] f(a) in Main at REPL[2]:1
[3] f(a, b) in Main at REPL[3]:1

```

Also, if I define the four methods in this order:

```julia
begin
	f()=1
	f(a)=2
	f(a,b)=3
	f(;a,b)=4
end

```

and run `f()` I get an Error: `UndefKeywordError: keyword argument a not assigned.

So I wasn’t sure that it was acceptable to have both an emtpy arg list method `f()` and a purely keyword-based method `f(; a,b)` defined at the same time.

So my surprise is that I get different behaviors depending on the order of the definitions and that in the original posted session, `methods(f)` listed 3 methods, but I could demonstrate 4.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 16, 2020, 7:27pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/4 "2020-10-16T19:27:07Z")

</div>

```julia
❯ julia --warn-overwrite=yes -q
julia> begin
           f()=1
           f(a)=2
           f(a,b)=3
           f(;a,b)=4
       end
WARNING: Method definition f() in module Main at REPL[1]:2 overwritten at REPL[1]:5.
f (generic function with 3 methods)

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 7:29pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/5 "2020-10-16T19:29:17Z")

</div>

Keyword arguments don’t participate in dispatch, so it is expected that `f() = 1` completely overrides the previous definition `f(; a, b) = 4` and that’s why there are only 3 methods listed. It also explains why `f()` works in your first example and not in your second example.

> [@klaff](#):
>
> ```julia
> julia> begin
> f(a)=2
> f(a,b)=3
> f(;a,b)=4
> f()=1
> end
> f (generic function with 3 methods)
> 
> julia> methods(f)
> # 3 methods for generic function "f":
> [1] f(; a, b) in Main at REPL[1]:5
> [2] f(a) in Main at REPL[1]:2
> [3] f(a, b) in Main at REPL[1]:3
> 
> ```

It looks like you actually stumbled upon a Julia bug here when printing the methodtable. The first method should be displayed as `f()`, not `f(; a, b)`. Would you mind opening an issue on GitHub about this?

Edit: Wait, in this example `f(a=1,b=2)` shouldn’t work, so this seems like an issue of the method overriding not working like it should, not just a printing bug.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 8:18pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/6 "2020-10-16T20:18:57Z")

</div>

I feel like I should win a prize if I’ve found a bug this simple!

Anyway, simplifying further:

Scenario 1:

```julia
C:\Users\klaff>julia -q
julia> f()=1
f (generic function with 1 method)

julia> f(;a)=2
f (generic function with 1 method)

julia> methods(f)
# 1 method for generic function "f":
[1] f(; a) in Main at REPL[2]:1

julia> f()
ERROR: UndefKeywordError: keyword argument a not assigned
Stacktrace:
 [1] f() at .\REPL[2]:1
 [2] top-level scope at REPL[4]:1

julia> f(a=1)
2

julia>

```

Scenario 2:

```julia
C:\Users\klaff>julia -q
julia> f(;a)=2
f (generic function with 1 method)

julia> f()=1
f (generic function with 1 method)

julia> methods(f)
# 1 method for generic function "f":
[1] f(; a) in Main at REPL[2]:1

julia> f()
1

julia> f(a=1)
2

julia>

```

I’m happy to make an issue although I’m not sure exactly what it is. I don’t think order of definition should affect whether a method gets overwritten (but it should affect which is left standing). Certainly in scenario 2 the return from `methods(f)` is non consistent with reality (both methods are reachable).

How do I know (from a doc standpoint) whether those two methods should be allowed to coexist?

EDIT: If you change the above to `f(;a=1)=2`, then there are no surprises Whichever is defined last is the one method you get.

---

<div class="post-metadata">

**Author:** ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)\
**Post date:** [October 16, 2020, 8:54pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/7 "2020-10-16T20:54:16Z")

</div>

This is not a bug but intended behavior of how function definitions with keyword arguments work internally (refer to the [developer documentation](https://docs.julialang.org/en/v1/devdocs/functions/#Keyword-arguments) for more information). Long story short, `f(; a) = 2` actually defines a `f()` method without any keyword arguments. If defined after `f() = 1`, this effectively overwrites the original definition of `f()`, and so call to `f()` now errors and asks for keyword argument `a`. In the second scenario, the `f() = 1` instead overwrites the `f()` method defined by `f(; a) = 2`, which is why `f()` will return 1.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 8:56pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/8 "2020-10-16T20:56:45Z")

</div>

> [@klaff](#):
>
> How do I know (from a doc standpoint) whether those two methods should be allowed to coexist?

They should never coexist at the same time, because they have exactly the same signature. (Keyword arguments aren’t actually part of a method’s signature.)

In scenario 1, everything is working as it should; `f()=1` gets overridden by `f(;a)=2`, so that’s exactly the behavior you observe.

In scenario 2, `f(;a)=2` should therefore also be completely overridden by `f()=1`, so `methods(f)` should only print `f()`, not `f(; a)` and `f(a=1)` should therefore be an `UndefVarError`.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 8:59pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/9 "2020-10-16T20:59:08Z")

</div>

The way function definitions are lowered should only be an implementation detail though, this seems more like an unintended side effect of that, instead of a feature. From a user perspective, this behavior really doesn’t make a lot of sense, at least to me.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 9:04pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/10 "2020-10-16T21:04:32Z")

</div>

I think you are correct, and this text from [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/) seems most relevant:

> 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’ll submit an issue against scenario 2.

---

<div class="post-metadata">

**Author:** ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)\
**Post date:** [October 16, 2020, 9:05pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/11 "2020-10-16T21:05:17Z")

</div>

Even if `f()` is overwritten in scenario 2, the keyword sorter and the compiler-generated function remains and so `f(; a)` would still work. I would say this is pretty intuitive behavior for me, since although the method signature is the same, method with keyword arguments is different from one without.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 9:09pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/12 "2020-10-16T21:09:24Z")

</div>

This still seems a bit like a potential pitfall to me, since it’s not at all clear form looking at `methods(f)` and it seems weird that defining them in different orders either overwrites the previous method of `f` completely or only partially.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 9:10pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/13 "2020-10-16T21:10:00Z")

</div>

I don’t think it can be correct that in scenario 2 there are two different return values. That’s inconsistent with `f()` being overwritten.

---

<div class="post-metadata">

**Author:** ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)\
**Post date:** [October 16, 2020, 9:14pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/14 "2020-10-16T21:14:55Z")

</div>

Calling `f(a=1)` doesn’t call `f()` but something along the line of `#f#1(a)`, which was defined with `f(; a)`. The `f()` definition only handles the case where no keyword is passed (default keyword argument value, for example).

---

<div class="post-metadata">

**Author:** ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)\
**Post date:** [October 16, 2020, 9:22pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/15 "2020-10-16T21:22:03Z")

</div>

Well in both cases the keyword sorter and the generated positional argument-only method still exist. The only method overridden is the call without any specified keyword, so I wouldn’t say the method was overwritten completely.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 9:22pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/16 "2020-10-16T21:22:45Z")

</div>

I entered an issue [https://github.com/JuliaLang/julia/issues/38066](https://github.com/JuliaLang/julia/issues/38066).

I’m a bit out of my depth at this point and will let wiser folks sort it out.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 9:26pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/17 "2020-10-16T21:26:27Z")

</div>

But AFAIK, it’s not callable in the current worldage anymore, so from a regular user’s perspective, I don’t see how that’s any different than the method being completely overridden.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [October 16, 2020, 9:29pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/18 "2020-10-16T21:29:05Z")

</div>

```julia
C:\Users\klaffedk>julia -q
julia> f(;a)=2
f (generic function with 1 method)

julia> f()=1
f (generic function with 1 method)

julia> @code_llvm f()

; @ REPL[2]:1 within `f'
; Function Attrs: uwtable
define i64 @julia_f_106() #0 {
top:
  ret i64 1
}

julia> @code_llvm f(a=1)

; @ REPL[1]:1 within `f##kw'
; Function Attrs: uwtable
define i64 @"julia_f##kw_133"([1 x i64]* nocapture nonnull readonly dereferenceable(8)) #0 {
top:
  ret i64 2
}

```

I can call both methods here.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 16, 2020, 9:29pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/19 "2020-10-16T21:29:51Z")

</div>

Sorry, I meant only in the first scenario

---

<div class="post-metadata">

**Author:** ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)\
**Post date:** [October 16, 2020, 9:45pm UTC](https://discourse.julialang.org/t/im-confused-about-methods/48508/20 "2020-10-16T21:45:43Z")

</div>

Perhaps the current behavior is not as intuitive, but it is sometimes useful to provide a default behavior for methods with keyword arguments. Maybe a warning in the REPL would help?

[Next page](https://discourse.julialang.org/t/im-confused-about-methods/48508.md?page=2)
