Function static parameter names not unique ? parametric type problem


#1

error:

ERROR: LoadError: syntax: function static parameter names not unique

I’ve been reading some of the posts about parametric types and inner constructors but I can’t quite seem to get what I’m trying to do to work.

Thanks,

type Point{T<:Real}
    x :: T
    y :: T
    z :: T
end

function convert{T<:Float64}(::Type{Point{T}}, xyz::Tuple{Float64,Float64,Float64})
    Point(xyz[1], xyz[2], xyz[3])
end

type Plate{T<:Real}
    p0 :: Point{T}
    p1 :: Point{T}
    function Plate{T<:Real}(p0::Point{T}, p1::Point{T})
        if ((p0.x == p1.x) || (p0.y == p1.y) || (p0.z == p1.z))
            new(p0, p1)
        else
            error("Plate definition must have 0 thickness in one dimension")
        end
    end
end

p1 = Plate(Point(3.0,4.0,5.0), Point(3.0, 7.0, 6.0))

#2

The Julia documentation has an example very similar to your case. It seems like you will need an inner constructor as well as an outer constructor. In detail, in your inner constructor, just write Plate instead of Plate{T<:Real} (but keep the Point{T}s – T is still defined from the type parameter), and then add the (seemingly tautological) outer constructor

Plate{T<:Real}(p0::Point{T}, p1::Point{T}) = Plate{T}(p0,p1)

This works for julia 0.5. AFAIK 0.6 has some changes to the inner constructor syntax, maybe there is a way to achieve the same thing without the outer constructor.


#3

It’s not your fault: 0.5 inner constructors are a little weird. (They actually implicitly add static type parameters in some situations. That’s why the error message mentions static parameter names not being unique.) Just make this small change and things will work.

type Point{T<:Real}
    x :: T
    y :: T
    z :: T
end

function convert{T<:Float64}(::Type{Point{T}}, xyz::Tuple{Float64,Float64,Float64})
    Point(xyz[1], xyz[2], xyz[3])
end

type Plate{T<:Real}
    p0 :: Point{T}
    p1 :: Point{T}
    function (::Type{Plate}){T<:Real}(p0::Point{T}, p1::Point{T})
        if ((p0.x == p1.x) || (p0.y == p1.y) || (p0.z == p1.z))
            new{T}(p0, p1)
        else
            error("Plate definition must have 0 thickness in one dimension")
        end
    end
end

p1 = Plate(Point(3.0,4.0,5.0), Point(3.0, 7.0, 6.0))

On 0.6, the 0.5 inner constructor weirdness is deprecated, and will go away in 1.0. For now, to avoid it, just explicitly write (::Type{Foo}) to make explicit what type a method is being added to.