# Method definition overwritten warning for functions with default arguments

**URL:** https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710
**Category:** General Usage
**Tags:** question
**Created:** [January 26, 2017, 10:28pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710 "2017-01-26T22:28:13Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 26, 2017, 10:28pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/1 "2017-01-26T22:28:13Z")

</div>

When defining multiple methods of the same function using default arguments, Julia generates extra methods to handle the syntactic sugar. But it can so happen that Julia will define the same methods for each of the methods I’m defining, effectively overwriting itself.

For example:

```julia
julia> bar(a::String = "") = "moo"
bar (generic function with 2 methods)

julia> bar(a::String = "", s::Symbol = :s) = "boo"
WARNING: Method definition bar() in module Main at REPL[12]:1 overwritten at REPL[13]:1.
WARNING: Method definition bar(String) in module Main at REPL[12]:1 overwritten at REPL[13]:1.
bar (generic function with 3 methods)

julia> bar(i::Int = 2) = "zee"
WARNING: Method definition bar() in module Main at REPL[13]:1 overwritten at REPL[15]:1.
bar (generic function with 4 methods)

```

The warning should be hidden since it’s part of Julia’s internals - it won’t help the developer and on the contrary, it’s confusing. I stumbled onto this in a scenario where I was myself dynamically generating various methods and it sent me on a wild goose chase.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 26, 2017, 10:40pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/2 "2017-01-26T22:40:47Z")

</div>

It’s not internal in the sense that it has observable effect that you’ll never be called the `bar()` version of the previous two methods anymore.

---

<div class="post-metadata">

### Author: ![joshday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joshday/32/368_2.png) [@joshday](https://discourse.julialang.org/u/joshday)
#### Post date: [January 26, 2017, 10:41pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/3 "2017-01-26T22:41:15Z")

</div>

This warning should definitely not be hidden. The method for `bar()` is overwritten because you are providing default arguments.

```julia
julia> bar(a::String = "") = "moo"
bar (generic function with 2 methods)

julia> bar()
"moo"

julia> bar(a::String = "", s::Symbol = :s) = "boo"
WARNING: Method definition bar() in module Main at REPL[1]:1 overwritten at REPL[3]:1.
WARNING: Method definition bar(String) in module Main at REPL[1]:1 overwritten at REPL[3]:1.
bar (generic function with 3 methods)

julia> bar()
"boo"

```

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 26, 2017, 10:44pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/4 "2017-01-26T22:44:38Z")

</div>

Also note that an alternative way is to treat method with default argument as a single method instead of multiple ones like what we do now. In that case, `bar()` won’t be overwritten but will be an ambiguity that needs to be resolved. The difference between the two approaches is also observable and not an internal detail and both should be equally valid.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 27, 2017, 11:34am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/5 "2017-01-27T11:34:17Z")

</div>

Thanks

OK, I see - I agree with your points.

But maybe the behavior can be improved? It now requires lower level understanding of how Julia handles methods with default arguments. And it seems to go against the principle of least surprise. We can conclude that the current implementation has, at least, a usability problem - which goes against the idea of having these methods in the first place (to make the language more friendly, DRY-er and usable for the developer).

@joshday Indeed, it is a serious issue and the warning can’t be hidden as the behavior causes very important and potentially critical side effects (another method might be called).

@yuyichao Maybe that could be a compiler option? Overwrite vs explicitly handle ambiguity? But this would still present the usability problem - it would just replace one problem with another. It will however be safer, which is a big deal.

* * *

Just brainstorming here, but would it be possible to have typed methods with 0 arguments?

Let’s take these two simple examples:

```julia
julia> baz(s::String = "hello") = s
baz (generic function with 2 methods)

julia> baz(i::Int = 2) = i
WARNING: Method definition baz() in module Main at REPL[19]:1 overwritten at REPL[20]:1.
baz (generic function with 3 methods)

```

Instead of having `baz()` with the same signature in both cases, could we have a `baz(::String)` and a `baz(::Int)` ?

This way  
1/ we’d have distinct methods  
2/ we’d have the option of invoking either with the default arguments, by literally calling `baz(::String)` or `baz(::Int)`

I guess this would still leave open the issue of `baz(::Any)` – but it would be more flexible as it would allow defining and invoking multiple methods for `baz()`.

---

<div class="post-metadata">

### Author: ![felix](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/felix/32/604_2.png) [@felix](https://discourse.julialang.org/u/felix)
#### Post date: [January 27, 2017, 12:15pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/6 "2017-01-27T12:15:20Z")

</div>

Default arguments are always a bit tricky, it reminds me of the infamous python `function f(a = [])` situation. Julia works quite nicely in comparison, but I see what you’re saying. I think people will be alright as long as they remember that

- for any method with default arguments, Julia creates a copy which takes less arguments
- methods are overwritten if they have the same signature

Both of those are useful, easily described, and easily discovered, so I’m happy with it.

It’s an interesting idea with the typed 0-argument case. (Although philosophically I find it hard to think about the type of something that is not there.) You could prepare a package, that would get people interested. You’d probably have to use macros to hook into the existing dispatch functionality, though, so it wouldn’t be entirely simple.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 27, 2017, 12:54pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/7 "2017-01-27T12:54:53Z")

</div>

> [@essenciary](#):
>
> It now requires lower level understanding of how Julia handles methods with default arguments.

It’s not lower level since you have to define a behavior for “conflicting” missing argument case. This (optional argument being equivalent to defining multiple methods) is also documented right when it is introduced ([http://julia.readthedocs.io/en/latest/manual/functions/#optional-arguments](http://julia.readthedocs.io/en/latest/manual/functions/#optional-arguments) and [http://julia.readthedocs.io/en/latest/manual/methods/#man-note-on-optional-and-keyword-arguments](http://julia.readthedocs.io/en/latest/manual/methods/#man-note-on-optional-and-keyword-arguments)) and is also observable if you run `methods` on any function you’ve defined this way.

> [@essenciary](#):
>
> We can conclude that the current implementation has, at least, a usability problem

What’s the usability problem?

> [@essenciary](#):
>
> Maybe that could be a compiler option? Overwrite vs explicitly handle ambiguity?

That will only make it worse.

> [@essenciary](#):
>
> Instead of having baz() with the same signature in both cases, could we have a baz(::String) and a baz(::Int) ?

At least that’s not how method overloading work so it would be a big semantic/syntax change. It should at least not be added as a special case for default argument.

---

<div class="post-metadata">

### Author: ![pint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pint/32/125_2.png) [@pint](https://discourse.julialang.org/u/pint)
#### Post date: [January 27, 2017, 1:38pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/8 "2017-01-27T13:38:56Z")

</div>

one does not even need to know the internals. the provided set of functions is ambiguous no matter what the internals are. in order to be well defined, for any combination of actual parameters it should be clear which version is to be called. and this is simply not the case if two methods accept zero parameters. this indicates that probably we are actually dealing with two functions here that happens to have the same name. maybe some refactoring is needed.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [January 27, 2017, 1:50pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/9 "2017-01-27T13:50:44Z")

</div>

It’s possible this behavior will change. See this issue:  
[https://github.com/JuliaLang/julia/issues/7357](https://github.com/JuliaLang/julia/issues/7357)

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 27, 2017, 2:00pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/10 "2017-01-27T14:00:09Z")

</div>

AFAICT that issue is about what to do after finding the right method and is irrelevant to this discussion which is only about how to find the right method.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [January 27, 2017, 2:04pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/11 "2017-01-27T14:04:43Z")

</div>

Right. It’s just related in that it will help simplifying this system. Though I agree that in the examples provided by the OP the methods clearly overlap and it doesn’t make sense defining conflicting optional arguments.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 28, 2017, 8:50am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/12 "2017-01-28T08:50:39Z")

</div>

Thank you all for the feedback, much appreciated.

@yuyichao The usability issue is in the fact that in other languages, defining methods with optional arguments Just Works ™. I’ve been programming in a few other for a while now and never ran into this kind of issue before.

Anyway, now that I fully understand the issue, I can handle it. It makes perfect sense in Julia but I have the tendency to ignore warnings early in the development phase. I think many devs are the same, and this one can bite badly.

I don’t have a strong opinion that something should be done about this - though I would like the typed 0 arguments methods, they’d make a nice addition and seem to fit in with Julia’s typing narrative. Maybe it will make more sense in the future, as the language evolves.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 28, 2017, 9:14am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/13 "2017-01-28T09:14:56Z")

</div>

I guess my surprise comes from the fact that I come from a lifetime of programming in weakly typed languages. These are all about the number of arguments - so methods with 2, 3, 4, etc optional arguments will not “leak” 0 arguments methods that overwrite each other. Arity is a core concept there.

In the same line of thought, this is a fairly low level implementation detail, as I have no idea how ruby, or PHP or JavaScript handle methods with optional arguments. I doubt many devs do, as with more mature / older languages people work with higher level frameworks and DSLs which require a massive time investment and level of mastery of their own.

As Julia will go mainstream it will be more and more about higher level frameworks and DSLs and books about these, and less about Julia itself. Ask yourself how many Rails _users_ (not contributors) have read the ruby manual?

It’s in this context where possible traps need to be avoided - and this is probably an ingredient for large scale adoption.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [January 28, 2017, 9:44am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/14 "2017-01-28T09:44:47Z")

</div>

> [@essenciary](#):
>
> As Julia will go mainstream it will be more and more about higher level frameworks and DSLs and books about these, and less about Julia itself. Ask yourself how many Rails users (not contributors) have read the ruby manual?

This argument (Julia did something I didn’t expect; this will be a problem when it goes mainstream, because my expectations describe the general population, so you should change the language) comes up here very often, many times each week.

Seemingly, there is a tradeoff between minimizing surprise for users coming with various prior histories of programming languages, and coming up with a small, easy to understand, consistent set of rules (which of course one has to learn, there is no way around that). But when these things are discussed, it turns out that people have a wide variety of intuitions about how things should work (because they worked that way in R/Matlab/Python/Ruby/…), so there is usually no DWIM solution that dominates the simple, consistent set of rules solution. See eg this thread and comment:

> [@A != b != c](https://discourse.julialang.org/t/a-b-c/1347/15):
>
> I think you’re getting at the real problem with this kind of discussion: people don’t all have the same intuitions, so debating intuitions doesn’t generally lead to any improvements in language design.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 28, 2017, 10:15am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/15 "2017-01-28T10:15:45Z")

</div>

@Tamas_Papp I agree, at this level, the discussion is too generic. But then again, this is relatively easy to address: what are the main approaches to dealing with methods with optional arguments? Are there any other schools of thought? Is Julia’s approach equally common?

Doing a bit more soul searching during breakfast, I’m actually starting to think that this approach might not be entirely consistent with Julia itself - and that arity should, maybe, be an important part in Julia’s implementation too.

The reason is that in Julia, a function in invoked by passing it a Tuple of arguments. A Tuple, by definition, has its type provided by the _number_ and types of its elements.

When I define a method, I define the type of Tuple it should be invoked with. So in this line of thinking, the method’s signature is defined in relation to the type of the Tuple of arguments it takes. Basically we have a method that is defined by its name the fact that it takes a number of exactly x arguments of exactly the types A, B, C, … .

In this reasoning, Julia defining other methods of different arity and types of its arguments Tuple, means constructing completely different methods altogether, with completely different signatures.

So why not always have a fixed method signature (in terms of the type of its Tuple of arguments – so arity and types) and instead have the Tuples that can be constructed with optional arguments?

I hope I managed to explain properly: it’s basically about having the type of the Tuple of arguments a strict part of a method’s signature and not generating methods that take different types of Tuples. Instead the Tuple itself would be more flexible, maintaining its type but accepting default arguments when constructed.

This could be a dedicated subtype of Tuple, like for example MethodArgumentTuple. And when defining methods with optional arguments, instead of generating methods for all the combinations of arguments, Julia would create a new instance of MethodArgumentTuple that would always have the same type (x elements of type A, B, C, …).

So no more `baz` but always `baz{MethodArgumentTuple{A, B, C}}` and the Tuple itself would provide the default arguments.

I guess it’s a variation of `baz(::String)` with a different approach: it’s not the function but the Tuple of arguments providing the values of the optional arguments.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 28, 2017, 12:21pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/17 "2017-01-28T12:21:46Z")

</div>

> [@essenciary](#):
>
> The usability issue is in the fact that in other languages, defining methods with optional arguments Just Works ™. I’ve been programming in a few other for a while now and never ran into this kind of issue before.

You have to and only have to deal with this issue when you have both multiple dispatch/overloading and optional argument. It’s the combination of the two that forces you to make a choice that’s user visible. Scripting/weakly typed languages usually don’t have the first so it’s not an issue for them. C++ kind of has both and they raise an error as long as your call have more than one matches (more or less) and I don’t think that’s better.

Disclaimer: I don’t know that many languages and it’d be interesting to know how other languages combines the too.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [January 28, 2017, 1:23pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/18 "2017-01-28T13:23:49Z")

</div>

I am sorry but I don’t think I understand what you are proposing. Each method already has a signature, that is matched for dispatch. It is just that optional arguments define extra methods, again with their own signatures.

BTW, did you read the discussion for the issue @nalimilan linked above? I think it is a reasonable solution.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [January 28, 2017, 3:43pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/19 "2017-01-28T15:43:43Z")

</div>

The problem you describe in the original post really cannot solved due to sheer logic: you defined both `bar(a::String = "")` and `bar(a::String = "", s::Symbol = :s)`. How could the language figure which method `bar()` should call? Clearly it does not make sense to make all arguments optional for both methods, you have to choose one. That really has nothing to do with Julia’s implementation.

---

<div class="post-metadata">

### Author: ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)
#### Post date: [January 29, 2017, 12:39pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/20 "2017-01-29T12:39:26Z")

</div>

@nalimilan By telling Julia what method I’m referring to. It boils back to having missing typed arguments - or making arity and the corresponding types (let’s call this arity+type) an integral part of a method’s signature.

With typed missing arguments, `bar()` would be `bar(::Any)`. Which would be different from `bar(::String)` and `bar(::String, ::Symbol)`. It could be invoked as `bar(::String)` or as `bar("Hi!", ::Symbol)`.

With arity+type notation it could be `bar<String,Symbol>()` corresponding to `bar(a::String = "", s::Symbol = :s)`. With invocations looking like `bar<String,Symbol>("Hi!")`.

I prefer the esthetics of the 2nd form, which would resemble the current `bar{T,N}` as `bar<T,N>` and would allow `bar<T,N>{T,N}`.

@Tamas_Papp Sorry, my example was too convoluted. I’m basically suggesting what’s above: that the original method signature (arity+types) stays “sticky”. And can be invoked explicitly; versus the current behavior where Julia takes a higher-arity-more-specific method and generates lower-arity-less-specific methods, losing track of what was the original method and creating overwriting methods. Makes sense?

Indeed, I’ve read the issue referenced by @nalimilan - I assume you’re referring to the `_hidden_f_` approach. Not sure how this would work with the examples we discussed, when higher-arity-more-specific methods generate less-specific-lower-arity methods?

It seems to me that

```julia
bar(s::String = "moo") 

```

and

```julia
bar(i::Int = 2)

```

would generate

```julia
bar() = _hidden_bar_("moo")

```

and

```julia
bar() = _hidden_bar_(2)

```

which would still be overwriting implementations.

Unless we go back again to my suggestion:

```julia
bar(::String) = _hidden_bar_("moo")

```

or

```julia
bar<String>() = _hidden_bar_("moo")

```

But of course, if we have `bar(::String)` or `bar<String>()` we don’t need `_hidden_bar_` anymore.

@yuyichao I understand. My point is no longer about the initial question (thank you all for clearing that out, btw), but rather about “can we think of a better way of doing this?”. In the end, the decision belongs to the core team - I just hope to offer a different (fresh?) perspective.

It took a bit of a detour but I’d say that the above defines my view of a possible implementation. Tagging method definitions with arity+type information which would allow the simultaneous definition of multiple methods without overwrites and would also allow disambiguation and explicit invocation. A possible syntax would be:

```julia
f<T,N>(x::T = T(), y::N = N()) = ... 

```

So for

```julia
bar(s = "", i = 42) = # ...

```

Julia would generate the tagged methods

```julia
bar<String,Int64>(s::String, i::Int64) 
bar<String,Int64>(s::String) 
bar<String,Int64>() 

```

And for

```julia
bar(s = "", sy = :s) = :x

```

Julia would generate

```julia
bar<String,Symbol>(s::String, sy::Symbol) 
bar<String,Symbol>(s::String) 
bar<String,Symbol>() 

```

For disambiguation, where necessary, we could invoke the desired method as

```julia
bar<String,Int>()

```

The tagged invocation would be optional and only required for disambiguation, plain `bar()` would still work if no ambiguities.

* * *

How other languages deal with this is indeed quite intriguing - I’ll do a bit of research into that, I’m curious too. If anything useful comes out, I’ll report back.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [January 29, 2017, 3:58pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/21 "2017-01-29T15:58:43Z")

</div>

OK, I didn’t understand your proposal then. But I don’t see how this would be an improvement over the current semantics. When there is a collision, it replaces accidental overwriting of methods with accidentally calling the other method, unless the ambiguity is resolved with the `<>` syntax, which would then introduce a new syntax for the sole purpose of solving a problem that replaced another problem.

[Next page](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710.md?page=2)
