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!