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}

Reply via email to