BTW, this thread might be relevant.
I tried with having a Vector of abstract types. Like this:
abstract type AbstractPlacement{T<:AbstractFloat} end
#---Volume-------------------------------------------------------------------------
struct Volume{T<:AbstractFloat, S<:AbstractShape{T}, M<:AbstractMaterial}
label::String
shape::S # Reference to the actual shape
material::M # Reference to material
daughters::Vector{AbstractPlacement{T}}
end
#---PlacedVolume-------------------------------------------------------------------
struct PlacedVolume{T<:AbstractFloat,S<:AbstractShape{T}, M<:AbstractMaterial} <: AbstractPlacement{T}
transformation::Transformation3D{T}
volume::Volume{T,S,M}
end
Volume{T}(label::String, shape::S, material::M) where {T,S,M} = Volume{T,S,M}(label, shape, material, Vector{AbstractPlacement{T}}())
The performance is twice worst than what I had originally.
Are you sure youâre not trying to express too much? Most of the time the compiler can figure out the types. Canât you just use a type parameter, and leave it to the compiler to find out what it is? Both a homogeneous and a heterogeneous vector can be expressed as Vector{T}
for some T
.
Sorry, perhaps I am not expressing myself well. In the system I developing I would be ending with about 20 different âshapesâ with more of less deep hierarchies. As I said, I can either have a unique Volume
that encapsulates a polymorphic shape and then have a homogenous vector of all the daughter volumes (this was the original design). Or, have a different Volume
type for each shape and have an heterogenous vector of daughters. I do not see how I can completely avoid polymorphism.
How heavy would be to change the max_methods
from 3 to something like 20?
What Iâm saying is that with this type specification
it is impossible to get the benefits when the vector genuinely is homogeneous. You are forcing the element type to always be abstract, even when itâs not necessary. If you instead use
daughters::Vector{T} # with T<: AbstractPlacement
you allow a concrete eltype when possible, and an abstract type when necessary.
yes, but each eltype is different in general. A âmotherâ volume may have âboxesâ, âtubesâ, âspheresâ, etc. as daughters.
Should work anyway. What am I missing?
Vector{T}
is a vector of âanythingâ, including arbitrarily nested types, type unions, or abstract types.
Is this the typocalypse?
For this kind of low-level polymorphism I would suggest moving the typing from the Julia type system to your own data. In other words, I suggest you create a single type that has as many Float64
âpointâ fields as you may need for your largest shape, and a single tag
field which the type is an @enum
of your 20 primitive shapes. Then write a single area
function that has a long if ...; ...; elseif ...; ...; end
that deals with your 20 possible cases. This is not easily extensible by third parties but will give you some idea of how fast your system could possible be.
Unityper, which I linked to before, tries to provide a more convenient API for this, and tries to compactify the final struct in the case where not all their fields are the same.
But you can also do it manually.
I would strongly recommend something like this approach.
Sorry if I am very slow to understand. I see that Vector{T} can be a vector of anything. But what I need is a vector that the elements are of different types all of them inheriting from some Abstract type.
In languages such as C++ this will be implemented with an abstract class (with pure visual methods). I start understanding that the Abstract type in Julia is not equivalent (as it is not used to define an API) and is only used as a pre-condition for argument checking.
Thanks. But honestly I was thinking that Julia would provide better help for this. This is equivalent of C or even lower, since there is no switch statement in Julia.
I was expecting that multi-dispatch would help me. I do have a reference to a AbstractShape
and the proper method is called for each of the shapes. What I cannot understand is why the compiler cannot infer what are return values, even if I specify them in the signature of the function. The other thing I do not understand is why there is memory allocation involved in the dispatching.
Yes, and Vector{T}
can express that. My point is that parameterizing like that leaves room either for a totally heterogeneous vector or for a homogeneous vector of concrete eltype.