# 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:** 11\
**Page:** 2

<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 29, 2017, 11:04pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/22 "2017-01-29T23:04:25Z")

</div>

i still believe that this is a refactoring situation. if you are willing to decorate your function with the input types, you could just as well add some postfix, like `barsym` and `barindex` or whatever the integer means.

---

<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 30, 2017, 6:35am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/23 "2017-01-30T06:35:53Z")

</div>

@Tamas_Papp The current semantics simply don’t permit the definition of multiple methods, which causes the overwrites in the first place. Then this could possibly be used to solve other related problems, such as the one we talked about earlier (with the `_hidden_f`).

@pint That would considerably reduce the flexibility of the API, especially when creating DSLs. My issue appeared while writing a DSL for a HTML-like (or rather HAML-like) templating engine. My goal was to come up with an easy to use syntax and provide helpful defaults. I dynamically generate methods corresponding to HTML elements, such as `span()`, `p()`, `div()`, etc. Using the `do` syntax this ends up looking very much like plain HTML. Doing things like `div_empty` or `div_with_attrs` or however you want to call them, would defeat the purpose.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 30, 2017, 8:15am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/24 "2017-01-30T08:15:03Z")

</div>

I must admit I don’t really understand your proposal, but why can’t you do this:

```julia
bar(a::String) = "moo"
bar(i::Int) = "zee"

bar(::Type{String}) = bar("")
bar(::Type{Int}) = bar(2)

julia> bar(String)
"moo"
julia> bar(Int)
"zee"

```

?

---

<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 30, 2017, 8:16am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/25 "2017-01-30T08:16:03Z")

</div>

that does not explain to me why do you want `bar()` to exist in two versions, one for omitted integer, one for omitted symbol (or any other signatures).

but if so, you can still abandon defaults, and provide your own default constant. like

```julia
const DEFBARINT = 7
bar(n::Int) = ...

bar(DEFBARINT)
# instead of bar<Int>() or bar(::Int)

```

after all, this is what “i want an int here, but i don’t tell what” actually means

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 30, 2017, 10:05am UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/26 "2017-01-30T10:05:19Z")

</div>

Elaborating a bit:

What you want is for the user of your code to be able to specify the type when s/he wishes to use a default value, right? I prefer my own suggestion to yours in that case: that the user calls

```julia
bar("Hello", Symbol)

```

to indicate that the default `Symbol` value should be used. In that case you are left with needing a convenient way of generating those extra definitions. As far as I understand, that is what macros are for:

You make a macro with catchy name, like `@usetypesasdefaults`, and then

```julia
@usetypesasdefaults foo(a::String = "", b::Int = 2) = [...]

```

gets rewritten to

```julia
foo(a::String, b::Int) = [...]
foo(::Type{String}, b::Int) = foo("", b)
foo(a::String, ::Type{Int}) = foo(a, 2)
foo(::Type{String}, ::Type{Int}) = foo("", 2)

```

For many inputs this can cause an explosion of methods, so maybe it could re-write to

```julia
function foo(a::Union{String, Type{String}, b::Union{Int, Type{Int}})
    if isa(a, DataType)
        a = ""
    end
    if isa(b, DataType)
        b = 2
    end
    [...]
end

```

This is just off the top of my head. There are probably ways to simplify this.

**Edit:** One other advantage (aside from not breaking most Julia code ever written) is that the user now only has to specify the type of the missing input, instead of _all_ the types (which might not even be known before run-time!!)

---

<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 30, 2017, 6:15pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/27 "2017-01-30T18:15:27Z")

</div>

I don’t really want `bar()` to exist in 2 versions – that was just a generalization (simplification) as the discussion moved up from my initial question.

My exact use case is this: I build a DSL for constructing HTML pages - a templating language similar to HAML. I have some functions that generate an HTML document. And I want them to be used like this:

```julia
DIV() do 
  H1() do 
    "Hello world!"
  end
end

```

But of course, an important part of HTML are the attributes. I want to be able to pass them. So I want to do:

```julia
A([:href => "http://...", :class => "menu", :onclick => "loginModal()"]) do 
  "Login"
end

```

But then I wanted to make it easy on the user of the API and avoid that she forgets the parenthesis so I made them optional, allowing:

```julia
H1(:class => "main", :style => "border: 1px solid red") do 
  "Welcome!"
end

```

Finally, there are empty HTML elements – I need these too: `HR(), BR()` etc. Since they’re void it means they can’t contain any other HTML element so they won’t need the first argument, the `Function`; but can very well have the 2nd, for the attributes.

In my code I have something like this:

```julia
const NORMAL_ELEMENTS = [:HTML, :HEAD, :BODY, :TITLE, :STYLE, :ADDRESS, :ARTICLE, :ASIDE, :FOOTER, ...]

function attributes(attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: Vector{String}
  a = String[]
  for (k,v) in attrs
    push!(a, "$(k)=\"$(v)\"")
  end

  a
end

function normal_element(f::Function, elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString
  a = attributes(attrs)

  """\n<$( string(lowercase(elem)) * (! isempty(a) ? (" " * join(a, " ")) : "") )>\n$(f())\n</$( string(lowercase(elem)) )>"""
end

function register_elements()
  for elem_name in NORMAL_ELEMENTS
    f_body = """
      function $elem_name(f::Function = ()->"", attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString
        \"\"\"\$(normal_element(f, "$(string(elem_name))", attrs))\"\"\"
      end
    """

    f_body |> parse |> eval

    f_body = """
      function $elem_name(f::Function = ()->"", attrs::Pair{Symbol,String}...) :: HTMLString
        \"\"\"\$($elem_name(f, [attrs...]))\"\"\"
      end
    """

    f_body |> parse |> eval
  end
end

```

It works quite well:

```julia
julia> Flax.DIV(:class => "main", :onclick => "go()") do
       "hello"
       end
"<div class=\"main\" onclick=\"go()\">\nhello\n</div>"

julia> Flax.HR()
"<hr>"

julia> Flax.BR(:class => "foo")
"<br class=\"foo\">"

```

but it causes Julia to output a long list of warnings as it generates overwriting methods. This is how it all started.

Now, I can find a way around them, I guess the simplest being by removing the version with the `Vector`. But I was wondering if there isn’t a way of avoiding that Julia creates this situation in the first place.

---

<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:** [January 30, 2017, 6:19pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/28 "2017-01-30T18:19:16Z")

</div>

> [@essenciary](#):
>
> H1(:class =\> “main”, :style =\> “border: 1px solid red”) do  
> “Welcome!”  
> end

Would standard Julia keyword arguments work?

```julia
H1(class="main", style="border")

```

The `Parameters.jl` package may also be relevant:

> **[GitHub - mauro3/Parameters.jl: Types with default field values, keyword...](https://github.com/mauro3/Parameters.jl)**
>
> Types with default field values, keyword constructors and (un-)pack macros - mauro3/Parameters.jl

---

<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 30, 2017, 6:27pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/29 "2017-01-30T18:27:21Z")

</div>

That’s interesting - and it does look pretty. I’ll try it out, thanks

---

<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 30, 2017, 6:31pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/30 "2017-01-30T18:31:11Z")

</div>

Yeah, definitely, that’d be even cleaner and save quite a few keystrokes. If it also helps me get rid of the warnings and the `parse |> eval` parts, that’d be super awesome. I’ll see if / how I can use it. Thanks for the tip.

---

<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:** [January 30, 2017, 6:37pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/31 "2017-01-30T18:37:32Z")

</div>

The syntax is something like

```julia
function H1(; class="main", style="")
     
end

```

(Note the `;` at the start to separate positional arguments from keyword arguments.)

[http://docs.julialang.org/en/stable/manual/functions/#keyword-arguments](http://docs.julialang.org/en/stable/manual/functions/#keyword-arguments)

---

<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 30, 2017, 10:54pm UTC](https://discourse.julialang.org/t/method-definition-overwritten-warning-for-functions-with-default-arguments/1710/32 "2017-01-30T22:54:41Z")

</div>

if i understand correctly, using your proposal, you had to write something like

```julia
DIV<Function,Pair{Symbol,String}...>()

```

which is quite ugly. however, this particular case can be solved by making f required, making the attr array required, and creating a new methods with no function.

```julia
DIV(f::Function, attrs::Vector{Pair{Symbol,String}}) = # normal_element thing
DIV(f::Function, attrs::Pair{Symbol,String}...) = DIV(f, Pair{Symbol,String}[attrs...])
DIV(attrs::Pair{Symbol,String}...) = DIV(()->"", attrs...)
DIV(attrs::Vector{Pair{Symbol,String}}) = DIV(()->"", attrs)

```

this way, the missing attribute case is catched by the , version as empty tuple. so you can call with any combination of function and either attribute list or array. i included the type in the array generation, so empty arrays get the correct type instead of Any.

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