Open briochemc opened 4 years ago
The solution is to always use a separate type parameter for every field. Whihc also has other benefits.
Mmm no I meant something different. Take a single field example:
julia> using FieldMetadata, Unitful
julia> import FieldMetadata: @units, units
julia> @units struct Foo{T}
a::T | u"m"
end
units (generic function with 11 methods)
julia> foo = Foo(1.0) # works as intended
Foo{Float64}(1.0)
julia> foo = Foo(1.0u"km") # should convert to 1000.0u"m", but does not...
Foo{Quantity{Float64,π,Unitful.FreeUnits{(km,),π,nothing}}}(1.0 km)
julia> Foo(args::Quantity...) = Foo([ustrip(x |> units(Foo, f)) for (x,f) in zip(args, fieldnames(Foo))]...)
julia> foo = Foo(1.0u"km") # now works as intended
Foo{Float64}(1000.0)
Ah ok the T in the first example confused me. That is an interesting problem. You could define T<:typeof(1.0u"m")
. I guess FieldDefaults.jl could define a constructor but its getting pretty case specific... I don't actually use units
, I just put them in the struct.
I was thinking about this toy example:
Now I can add a specific constructor to deal with Unitful arguments:
I'm pretty sure my solution is not optimal but anyway, do you think it is possible to automatically generate that constructor (that takes in units and converts them) if
@units
is used?