I’m trying to build a data type to hold a measurements of a quantity. I know that this quantity will be a length, but don’t know a priori what unit that length will be. I’m having a bit of trouble coming up with syntax to guarantee that heights will be a length using the Unitful types.
using Unitful
struct Measurements
heights::Array{Unitful.Quantity,1} # this line
end
Is there a better way to do this? Thanks for the help!
julia> struct Measurements{T <: Quantity{<:Any, Unitful.𝐋}}
heights::Vector{T}
end
julia> Measurements([1u"m", 2u"cm"])
Measurements{Quantity{Rational{Int64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}}(Quantity{Rational{Int64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}[1//1 m, 1//50 m])
julia> Measurements([1u"m", 2u"s"])
ERROR: MethodError: no method matching Measurements(::Array{Quantity{Int64,D,U} where U where D,1})
Edit: If you don’t want the type parameter you can use
julia> struct Measurements
heights::Vector{<: Quantity{<:Any, Unitful.𝐋}}
end
You can also just specify a specific length unit, and on insertion convert from the given length to the length required by the vector. Is there a reason you want to keep track of what unit was originally provided?
This may actually be a better approach – there is no need to track the original unit and it would be helpful to convert by default to a unit (say feet)
Cool, if one wanted to convert to feet by default is a constructor the place to do it? Something like
struct Measurements
heights::Vector{<: Unitful.Length}
function Measurements(x::Vector{<: Unitful.Length})
x_conv = [Unitful.uconvert(Unitful.u"ft", xi) for xi in x]
new(x_conv)
end
end
To make your struct concrete, but also more flexible, I’d do something like this:
#+begin_src julia
using Unitful
struct Measurements{T <: Unitful.Length}
heights::Vector{T}
Measurements(x::Vector{<: Unitful.Length}) = [Unitful.uconvert(Unitful.u"ft", xi) for xi in x]
end
Measurements([1u"cm", 1.0u"mm", 1e10u"fm"])
#+end_src
#+RESULTS:
: 3-element Array{Quantity{Float64,𝐋,Unitful.FreeUnits{(ft,),𝐋,nothing}},1}:
: 0.03280839895013123 ft
: 0.0032808398950131233 ft
: 3.280839895013124e-5 ft