Thank you, that works. I suppose I will have to use a generated function to make this type-stable.
On Wed, Aug 17, 2016 at 1:02 AM, Mauro <mauro...@runbox.com> wrote: > > On Wed, 2016-08-17 at 05:04, Cedric St-Jean <cedric.stj...@gmail.com> > wrote: > > Hi, I'm writing a function to recursively traverse a heterogeneous tree > of > > immutables and replace certain elements of it. So far I have: > > > > subst(x::Number, assoc::Associative) = x > > subst(x::Variable, assoc::Associative) = get(assoc, x, x) > > subst{T}(x::T, assoc::Associative) = T([subst(getfield(x, f), assoc) for > f > > in fieldnames(x)]...) > > > > I.e. numbers are kept as is, variables are possible replaced, and > composite > > structures are recursively traversed. This doesn't look very > > compiler-friendly, so question 1 is if there's a better way of writing > > this, short of manually writing one `subst` for each type. > > > > My problem is that the above fails when the composite structure is > > parametric, since a Variable might be replaced by a number. Eg. `Pair(2, > > Variable(:x))` will become `Pair(2, 5)`, and that's a different type, so > > the T([ ]...) line fails because T is Pair{Int, Variable}. > > > > Question 2 is: given T = Pair{Int, Int}, is there any way to recover > Pair? > > Pair{Int, Int}.name returns Pair, but as a TypeName. > > julia> Pair{Int, Int}.name.primary > Pair{A,B} > > But it's not type stable: > > julia> f(z) = z.name.primary > f (generic function with 1 method) > > julia> @code_warntype f(Pair{Int,Int}) > Variables: > #self#::#f > z::Type{Pair{Int64,Int64}} > > Body: > begin > return (Core.getfield)((Core.getfield)(z::Type{Pair{Int64, > Int64}},:name)::TypeName,:primary)::Type{T} > end::Type{T} >