I've been bitten by this many times and see so many others being bitten. I
know the docs explain this as well as I could, but it would be great if
someone could come up with some educational magic to improve the docs a bit
more.
On Saturday, June 4, 2016 at 10:17:16 AM UTC+8, David P. Sanders wrote:
>
>
>
> El viernes, 3 de junio de 2016, 22:06:20 (UTC-4), xdavidliu escribió:
>>
>> with
>>
>>
>> type foo
>> x::Int
>> foo(x) = x > 0 ? new(x) : new(-x)
>> end
>>
>>
>> type bar{T<:Integer}
>> x::T
>> end
>>
>>
>> type baz{T<:Integer}
>> x::T
>> baz(x) = x > 0 ? new(x) : new(-x)
>> end
>>
>>
>>
>> "foo(-5).x" gives 5, "bar(-5).x" gives -5, but "baz(-5).x" gives a
>> "MethodError: 'convert' has no method matching..." error.
>>
>> It seems the relevant section in the manual is this
>> <http://docs.julialang.org/en/release-0.4/manual/constructors/#parametric-constructors>,
>>
>> but I only have a single field (as opposed to the examples in the link in
>> which there are almost always two or more fields), so there should be no
>> type disagreement or ambiguity here. Is this intended behavior?
>>
>
> This is rather subtle.
> The inner constructor defines *only* the parametrised constructor:
>
> julia> type baz{T<:Integer}
> x::T
> baz(x) = x > zero(x) ? new(x) : new(-x)
> end
>
> julia> methods(baz)
> 2-element Array{Any,1}:
> call{T}(::Type{T}, arg) at essentials.jl:56
> call{T}(::Type{T}, args...) at essentials.jl:57
>
> julia> baz{Int}(-5)
> baz{Int64}(5)
>
> If you want to use a non-parametrized constructor like baz(-5), you need
> to explicitly define it:
>
> julia> baz{T}(x::T) = baz{T}(x)
>
> Note that on the left, this means "for each T, define a function baz(x)
> for x of that type"; on the right it tells you to call the parametric
> constructor with *that particular* type T:
>
> julia> baz(-5)
> baz{Int64}(5)
>
>