How to define NamedTuple types in struct?

I can implement the next code:

struct data
    p::NamedTuple{(:a,:b,:c,:d,:e), Tuple{Symbol,Bool,Any,Any,Any}}
end

q1 = data((a=:n,b=true,c="one",d=1,e=1.2))
q2 = data((a=:n,b=false,c="one",d=3.5,e=nothing))
#I get
julia> typeof(q1.p)
NamedTuple{(:a, :b, :c, :d, :e),Tuple{Symbol,Bool,Any,Any,Any}}

typeof(q2.p)
NamedTuple{(:a, :b, :c, :d, :e),Tuple{Symbol,Bool,Any,Any,Any}}

(a) How can I group the structure types without using abstract types? I am hoping to get:

# Expected result
julia> typeof(q1.p)
NamedTuple{(:a, :b, :c, :d, :e),Tuple{Symbol,Bool,String,Int64,Float64}}

julia> typeof(q2.p)
NamedTuple{(:a, :b, :c, :d, :e),Tuple{Symbol,Bool,String,Float64,Nothing}}

(b) Is there any way to define only the first two parameters?

struct data
    p::NamedTuple{(:a,:b,:c,:d,:e), Tuple{Symbol,Bool,...}}
end

You can parametrize your type:

struct data{T1,T2,T3}
    p::NamedTuple{(:a,:b,:c,:d,:e), Tuple{Symbol,Bool,T1,T2,T3}}
end

1 Like

@sairus7 Now it’s works, thank you so much for your help.

I have another question
I this case the structure has dictionaries

struct data{T}
    d::Dict{String,NamedTuple{(:a,:b,:c), Tuple{Symbol,T,T}}}
end

# the values of b and c are equal
dt = data( Dict( "p"=>(a=:n,b=1,c=1), "q"=>(a=:m,b=2,c=4) ) )

How can I parametrize the types so NameTuples can accept different type values?

e.g.

#the values of b and c are different
dt = data( Dict( "p"=>(a=:n,b=1.2,c=1.3), "q"=>(a=:m,b=nothing,c=nothing) ) )

My understanding is that it is possible to make a union of types Union{Real,Nothing}

julia> struct data
           d::Dict{String,NamedTuple{(:a,:b,:c), <:Tuple{Symbol,T,T} where T}}
       end

julia> dt = data( Dict( "p"=>(a=:n,b=1.2,c=1.3), "q"=>(a=:m,b=nothing,c=nothing) ) )

data(Dict{String,NamedTuple{(:a, :b, :c),#s1} where #s1<:(Tuple{Symbol,T,T} where T)}("q" => (a = :m, b = nothing, c = nothing),"p" => (a = :n, b = 1.2, c = 1.3)))

If you know that you only need a concrete <::Real type and Nothing, you can do eg

const myNT{T} = NamedTuple{(:a,:b,:c), Tuple{Symbol,T,T}}

struct Data{T <: Real}
    d::Dict{String,Union{myNT{T},myNT{Nothing}}}
    Data{T}() where T = new{T}(Dict{String,Union{myNT{T},myNT{Nothing}}}())
end

dt = Data{Float64}()

dt.d["p"] = (a=:n,b=1.2,c=1.3)
dt.d["q"] = (a=:m,b=nothing,c=nothing)

but if T itself is abstract (eg Real) this is unlikely to result in performant code (this may not matter of course).

1 Like