I have a type, let’s call it Special <: Real, which wraps a vector of lengthN. I have defined methods of most standard functions. Sometimes, however, one or several objects of type Special are nested deep into some outer type Outer and my usage of Special inside Outer fails. I would then like to construct one Outer for each value in the vector that Special wraps.
Say the situation is the following:
struct Special
x::Vector{Float64}
end
struct Outer{T}
a::T
b::Int
end
a = Outer(Special(randn(3)), 1)
More specifically, I would like to create a workspace object b which is an identical copy of a, except every occurance of an object of type Special is replaced by one of the floats inside the vector Special wraps. To perform computations on b N times.
I have looked at Nested.jl and it’s relative Flatten.jl, which allow me to “flatten” a nested structure and later reconstruct it. It’s close to what I need, but I also need to replace occurances of Special with Float64 in the the structure. I can’t really understand if Flatten.jl would allow me to do this or not, it’s implementation is very nontrivial.
Some details:
Special is my type, I have full control over its definition. Outer is not mine and I can not control it. I only have access to the object a below.
Preferably, I would like to avoid requiring the user to define any methods to get this to work.
I made an attempt at replacing all occurances of Special which works, but it only get’s me half way:
function build_container(P)
P isa Special && (return 0.0) # This replaces a Special with a float
P isa Number && (return P)
if P isa AbstractArray # Special handling for arrays
return map(build_container, P)
end
fields = map(fieldnames(typeof(P))) do n
f = getfield(P,n)
build_container(f)
end
fields
end
julia> a = Outer(Special(randn(3)), 1)
Outer{Special}(Special([0.2252388048584368, -1.79643970302527, 0.19512554621122083]), 1)
julia> build_container(a)
(0.0, 1)
julia> a = Outer([Special(randn(3)), Special(randn(3))], 1)
Outer{Array{Special,1}}(Special[Special([0.21367693941408203, -1.3515443961700613, 1.3534416611576705]), Special([-1.0929970912074651, -0.8659938973725613, -1.3585774872551668])], 1)
julia> build_container(a)
([0.0, 0.0], 1)
Now this works, but it only gets me halfway there, I need to reconstruct the flattend structure into the appropriate type with Special replaced with Float64, and here I get lost. Without assuming that Outer has a constructor that accepts all fields in order, I can not create it with my “container”.
Any pointers to direct me forward would be greatly appreciated!