# Constructor bug, what am I missing?

This construct bug is so strange, I can’t find where I am wrong.

``````struct tcg{F,T}
a::F
b::T
tcg(b::T,a::F=nothing) where {F,T}=new{F,T}(a,b)
tcg(a::F,b::T) where {F,T}=new{F,T}(a,b)
end
``````
``````tcg(10)

``````

The outcome should be this?

``````tcg{Nothing,Int64}(nothing,10)
``````

But acctually, it is:

``````tcg{Int64, Nothing}(10, nothing)
``````

Where am I going wrong?

Case 1:

``````struct tcg{F,T}
a::F
b::T
#= tcg(b::T,a::F=nothing) where {F, T} = begin
@show :tcg1
new{F,T}(a,b)
end =#
tcg(a::F,b::T) where {F, T} = begin
@show :tcg2
new{F,T}(a,b)
end
end

tcg(10)
``````

yields the expected

``````ERROR: MethodError: no method matching tcg(::Int64)
``````

Case 2:

``````struct tcg{F,T}
a::F
b::T
tcg(b::T,a::F=nothing) where {F, T} = begin
@show :tcg1
new{F,T}(a,b)
end
tcg(a::F,b::T) where {F, T} = begin
@show :tcg2
new{F,T}(a,b)
end
end

tcg(10)
``````

yields

``````:tcg2 = :tcg2
``````

This seems to be a worthy new issue.

To workaround the problem for the time being you could use

``````struct tcg{F,T}
a::F
b::T
tcg(b::T,a::Nothing) where {T} = begin
@show :tcg1
new{Nothing,T}(a,b)
end
tcg(a::F,b::T) where {F, T} = begin
@show :tcg2
new{F,T}(a,b)
end
end

tcg(10)
``````

yielding

``````:tcg1 = :tcg1
``````
1 Like

This is documented and intentional behaviour: Methods · The Julia Language

Basically `f(x, y=default) = ...` is just shorthand for two method definitions:

``````f(x, y) = ...
f(x) = f(x, default)
``````

``````tcg(b::T, a::F) where {F,T} = new{F,T}(a,b)
tcg(b::T) where {F,T} = tcg(b, nothing)
tcg(a::F, b::T) where {F,T} = new{F,T}(a,b)
``````

and since `F` and `T` are unconstrained, the third method overwrites the first one, so that `tcg(b::T)` calls the third method.

I think you probably want these two constructors:

``````tcg(b) = tcg(nothing, b)
tcg(a::F, b::T) where {F,T} = new{F,T}(a,b)
``````
3 Likes