Hi Tim,
That's a shame, I was hoping that doing the above would let me create
several different concrete PhylogenyNode and PhylogenyEdge types, that can
be used together. I guess since this is an abuse I have to pair one
concrete PhylogenyEdge type with one concrete PhylogenyNode type? I
wondered is a valid alternative to do something like this:
abstract AbstractNode
abstract PhylogenyNode <: AbstractNode
abstract NetworkNode <: AbstractNode
abstract AbstractEdge
abstract PhylogenyEdge <: AbstractEdge
abstract NetworkEdge <: AbstractEdge
type Branch <: PhylogenyEdge
from::PhylogenyNode
to::PhylogenyNode
length::Float64
function Branch()
x = new()
length!(x, -1.0)
return x
end
end
type Clade <: PhylogenyNode
from::PhylogenyEdge
to::Vector{PhylogenyEdge}
confidence::Float64
function Clade()
x = new()
x.to = Vector{PhylogenyEdge}()
confidence!(x, -1.0)
return x
end
end
And define getters and setters in such a way that type assertions make
things certain for the compiler?
I saw that Jeff proposed a similar solution in julia issue #269 to handle
circular type declarations.
On Wednesday, August 24, 2016 at 4:11:06 PM UTC+1, Tim Holy wrote:
>
> I don't think that's type-stable. Since each node of each tree will also
> be a
> different type, I also think you'll end up hating life due to compile
> times.
> There's some (peripherally) relevant discussion at http://docs.julialang.org/
>
> en/latest/manual/performance-tips/#the-dangers-of-abusing-multiple-dispatch-
>
> aka-more-on-types-with-values-as-parameters
> <http://docs.julialang.org/en/latest/manual/performance-tips/#the-dangers-of-abusing-multiple-dispatch-aka-more-on-types-with-values-as-parameters>
>
>
> Best,
> --Tim
>
> On Tuesday, August 23, 2016 3:28:17 PM CDT Ben Ward wrote:
> > I'm doing some development and wondered if this kind of pattern is
> > problematic:
> >
> > abstract AbstractNode
> > abstract PhylogenyNode <: AbstractNode
> > abstract NetworkNode <: AbstractNode
> > abstract AbstractEdge
> > abstract PhylogenyEdge <: AbstractEdge
> > abstract NetworkEdge <: AbstractEdge
> >
> > type Branch{N <: PhylogenyNode} <: PhylogenyEdge
> > from::N{Branch}
> > to::N{Branch}
> > length::Float64
> >
> > function Branch{N}(::Type{N})
> > x = new()
> > length!(x, -1.0)
> > return x
> > end
> > end
> >
> > type Clade{E <: PhylogenyEdge} <: PhylogenyNode
> > from::E
> > to::Vector{E}
> > confidence::Float64
> >
> > function Clade{E}(::Type{E})
> > x = new()
> > x.to = Vector{E}()
> > confidence!(x, -1.0)
> > return x
> > end
> > end
> >
> >
> >
> > As you can see both concrete types are parametric, and as a result there
> is
> > a certain circularity to it
> > Clade{Branch{Clade{Branch{Clade{Branch}}}}}.... That ultimately ends in
> > something like Clade{Branch{N<:PhylogenyNode}}. I'd like to know if this
> is
> > type-certain or not - the fact it terminates in N<:PhylogenyNode or
> > E<:PhylogenyEdge makes me doubt it.
>
>
>