Slightly ancillary, but perhaps relevant: the part that I struggled with
around this notation was understanding/remembering that

1) outer constructors are just normal functions
2) for parametric types, defining any inner constructor means there's no
default constructor
3) when there's no default constructor, all constructors must be called
with a type parameter

Regarding 1), I thought it was really strange that one has to write

Point{T<:Real}(x::T, y::T) = Point{T}(x,y)

until I realized that T in the first set of braces is a function type
parameter (i.e., specializing the function), and the second is a
specialization of the constructed type.

Hope someone finds this helpful.

Cheers, Kevin

On Mon, Apr 21, 2014 at 4:34 PM, Spencer Lyon <spencerly...@gmail.com>wrote:

> Matt, that is exactly what I was missing. I can't believe I missed that
> section of the docs. Thanks!
>
>
> On Monday, April 21, 2014 4:25:51 PM UTC-4, Matt Bauman wrote:
>>
>> I remember getting caught on this, as well.  I think I had to read the
>> section on Parametric 
>> Constructors<http://docs.julialang.org/en/latest/manual/constructors/#parametric-constructors>
>>  in
>> the docs about 5 times before finally understanding it.  Basically, the
>> implicit constructor is the same as defining the following inner *and*
>> outer constructors:
>>
>> type Point{T<:Real}
>>
>>   x::T
>>
>>   y::T
>>
>>   Point(x::T, y::T) = new(x,y)
>> end
>>
>> Point{T<:Real}(x::T, y::T) = Point{T}(x,y)
>>
>>
>> If you define any custom inner constructors yourself, the outer
>> constructor is no longer automatically defined for you.  There are quite a
>> few very fine semantic points about *why* this kind of definition is
>> required.  I still have to re-read that section every now and again to
>> remind myself.  But I don't think I can say it any better myself, at least
>> not yet.
>>
>> On Monday, April 21, 2014 3:47:40 PM UTC-4, Spencer Lyon wrote:
>>>
>>> I am having issues defining constructors for parametric types. I’lll
>>> borrow an example from the docs to illustrate my issue:
>>>
>>> Say I define this type:
>>>
>>> type Point1{T}
>>>   x::T
>>>   y::T
>>> end
>>>
>>> I can then create an object of this type in many ways
>>>
>>> julia> Point1(1.0, 2.0)
>>> Point1{Float64}(1.0,2.0)
>>>
>>> julia> Point1(1, 2)
>>> Point1{Int64}(1,2)
>>>
>>> julia> Point1("1", "2")
>>> Point1{ASCIIString}("1","2")
>>>
>>> julia> Point1('1', '2')
>>> Point1{Char}('1','2')
>>>
>>> julia> methods(Point1)
>>> # 1 method for generic function "Point1":
>>> Point1{T}(x::T,y::T)
>>>
>>> # ect...
>>>
>>> My question is how can I manually define the constructor for this
>>> Parametric type?
>>>
>>> To illustrate my issue, I tried to define a second type Point2 with the
>>> same fields. After reading the documentation sections on types, methods,
>>> and constructors I thought that I might be able to define the inner
>>> constructor as Point2(x, y) = new(x, y) as follows:
>>>
>>> type Point2{T}
>>>   x::T
>>>   y::T
>>>
>>>   Point2(x, y) = new(x, y)
>>> end
>>>
>>> However, this does not work:
>>>
>>> julia> Point2(1.0, 2.0)
>>> ERROR: no method Point2{T}(Float64, Float64)
>>>
>>> julia> methods(Point2)
>>> # 0 methods for generic function "Point2":
>>>
>>> I thought maybe I needed to include the paramter T in the constructor,
>>> but this doesn’t work either:
>>>
>>> type Point2{T}
>>>   x::T
>>>   y::T
>>>
>>>   Point2{T}(x, y) = new(x, y)
>>> end
>>>
>>> It is odd, however, that if I pass in a DataType when calling my 
>>> Point2constructor it does work. For example:
>>>
>>> julia> Point2{Float64}(1.0, 2.0)
>>> Point2{Float64}(1.0,2.0)
>>>
>>>

Reply via email to