from http://docs.julialang.org/en/latest/manual/constructors/
...This automatic provision of constructors is equivalent to the following
explicit declaration:
type Point{T<:Real}
>
> x::T
>
> y::T
>
>
>> Point(x,y) = new(x,y)
>
> end
>
>
>> Point{T<:Real}(x::T, y::T) = Point{T}(x,y)
>
>
Some features of parametric constructor definitions at work here deserve
comment. ...
Would adding a highlighted/bold/italicized note before "Some features..."
help? e.g.
*Important*
When an inner constructor is specified for a parameterized type, it is
necessary to include the corresponding outer constructor to allow
construction where the parameter value is not given explicitly.
type TimesTwo{T<:Real}
> x::T
> TimesTwo(x) = new(2*x) # inner constructor
end
TimesTwo{T<:Real}(x) = TimesTwo{T}(x) # outer constructor matching the
> inner constructor
Without the matching outer constructor, you can do: a = TimesTwo{Int}(5),
> but you cannot do a = TimesTwo(5). With the matching outer constructor,
> you can do both.
>
On Saturday, June 4, 2016 at 12:00:22 AM UTC-4, Eric Forgy wrote:
>
> 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)
>>
>>
>