Julia does not permit such syntax but what I want is basically
struct A{T, 2}
x::T
y::T
end
struct A{T, 3}
x::T
y::T
z::T
end
struct A{T, 4}
x::T
y::T
z::T
w::T
end
i.e., the number in type parameter matches the number of fields. The fields could contain x, y, z, w, a, b, c, d...
, and so on.
Is there a way of doing this?
Thank you, I know FieldVector
, but what I am concerned here is that why I should have
struct A2{T}
x::T
y::T
end
struct A3{T}
x::T
y::T
z::T
end
struct A4{T}
x::T
y::T
z::T
w::T
end
rather than generating the fields dynamically? The A
s are closely related and I do not want 3 types. Sorry, I should have been clearer.
Why does it have to be fields? Maybe a single (named) tuple as a replacement is fine? You could even overwrite getproperty
to make it feel like fields.
2 Likes
That’s a good idea. But I am just curious about whether Julia provides us such capability.
You can overload getproperty
to get the behavior you like without enumerating types.
julia> struct A{N, Ttuple <: NTuple{N}}
t::Ttuple
end
julia> function Base.getproperty(a::A{N}, s::Symbol) where {N}
s === :x && N >= 1 && return getfield(a, :t)[1]
s === :y && N >= 2 && return getfield(a, :t)[2]
s === :z && N >= 3 && return getfield(a, :t)[3]
s === :w && N >= 4 && return getfield(a, :t)[4]
return getfield(a, s)
end
julia> a = A((1,2,3,4));
julia> a.x
1
julia> a.y
2
julia> a.z
3
julia> a.w
4
julia> a = A((1,2,3));
julia> a.w
ERROR: type A has no field w
Stacktrace:
[1] getproperty(::A{3,Tuple{Int64,Int64,Int64}}, ::Symbol) at .\REPL[45]:6
Do you want to generate the values dynamically, or the valid field names?
Why would you do this and not use a NamedTuple
?
julia> a = (x=1, y=2, z=3)
(x = 1, y = 2, z = 3)
julia> a.x
1
julia> a.y
2
julia> a.z
3
julia> a.w
ERROR: type NamedTuple has no field w
Stacktrace:
[1] getproperty(::Any, ::Symbol) at .\sysimg.jl:18
2 Likes
Pure laziness to type x =
, y =
etc.
You can easily create a “constructor”,
julia> function A(v)
k = (:x, :y, :z, :w)
NamedTuple{k[eachindex(v)]}(v)
end
A (generic function with 1 method)
julia> a = A((1,2,3))
(x = 1, y = 2, z = 3)
julia> a = A((1,2,3,4))
(x = 1, y = 2, z = 3, w = 4)
EDIT: A(v)
isn’t type stable here which could easily be healed if we restrict the input to be Tuple
s.
1 Like
I want to generate the valid field names dynamically.
If you want the a.b
syntax, you should probably define methods for Base.propertynames
and Base.getproperty
. See the docs.