# Don't understand behaviour of NamedTuple{...,Tuple{...,T}} where T

**URL:** <https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382>\
**Category:** New to Julia\
**Tags:** question, type, behavior\
**Created:** [September 10, 2020, 1:26pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382 "2020-09-10T13:26:25Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Graham\_Gill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/graham_gill/32/9269_2.png) [@Graham\_Gill](https://discourse.julialang.org/u/Graham_Gill)\
**Post date:** [September 10, 2020, 1:26pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/1 "2020-09-10T13:26:25Z")

</div>

Here’s an example to enter in the REPL. I don’t understand the behaviour of `Z(x)` below.  
I’m using Julia 1.4.2.

```julia
julia> Y = NamedTuple{(:a,:b), Tuple{String,Real}}
julia> Z = NamedTuple{(:a,:b), Tuple{String,T}} where T <: Real
julia> f(y::Y) = y
julia> g(z::Z) = z

julia> x = (a = "abc", b = 1)

julia> f(x) # MethodError as expected
julia> g(x) # produces x as expected

julia> Y(x) # expected behaviour
NamedTuple{(:a, :b),Tuple{String,Real}}(("abc", 1))

julia> Z(x) # I don't understand this error - "T not defined"
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] NamedTuple{(:a, :b),Tuple{String,T}} where T<:Real(::NamedTuple{(:a, :b),Tuple{String,Int64}}) at ./namedtuple.jl:85
 [2] top-level scope at REPL[9]:1
 [3] eval(::Module, ::Any) at ./boot.jl:331
 [4] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [5] run_backend(::REPL.REPLBackend) at /home/graham/.julia/packages/Revise/ucYAZ/src/Revise.jl:1184
 [6] top-level scope at none:0
 [7] eval(::Module, ::Any) at ./boot.jl:331
 [8] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [9] run_backend(::REPL.REPLBackend) at /home/graham/.julia/packages/Revise/ucYAZ/src/Revise.jl:1184
 [10] top-level scope at none:0

```

Why is “T not defined”?

I’m trying to create a single type alias that I can use both in the context of method signatures and as a constructor of NamedTuples. I thought Z above was the way to go. Variations on Z don’t work or are equal to Y:

```julia
julia> NamedTuple{(:a,:b), Tuple{String,T} where T <: Real}
ERROR: NamedTuple field type must be a tuple type

julia> NamedTuple{(:a,:b), Tuple{String,T where T <: Real}} == Y
true

julia> NamedTuple{(:a,:b), Tuple{String,<: Real}}
ERROR: NamedTuple field type must be a tuple type

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [September 10, 2020, 1:48pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/2 "2020-09-10T13:48:32Z")

</div>

I may be wrong, but I think your problem is that:

```julia
julia> Z = NamedTuple{(:a,:b), Tuple{String,T}} where T <: Real
NamedTuple{(:a, :b),Tuple{String,T}} where T<:Real

julia> isconcretetype(Z)

```

In other words, `Z` is a abstract type, it serves the purpose of dynamic dispatch (so you can use it as the type of a parameter and it works as expected) but you cannot create an instance of it. I am actually surprised that `Z(x)` did not give a better error message, saying there was no constructor for the abstract type.

---

<div class="post-metadata">

**Author:** ![Graham\_Gill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/graham_gill/32/9269_2.png) [@Graham\_Gill](https://discourse.julialang.org/u/Graham_Gill)\
**Post date:** [September 10, 2020, 2:12pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/3 "2020-09-10T14:12:07Z")

</div>

OK thanks Henrique, that explanation sounds right to me, even though the `UndefVarError` is confusing.

---

<div class="post-metadata">

**Author:** ![Graham\_Gill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/graham_gill/32/9269_2.png) [@Graham\_Gill](https://discourse.julialang.org/u/Graham_Gill)\
**Post date:** [September 10, 2020, 10:10pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/4 "2020-09-10T22:10:35Z")

</div>

Here’s a followup question: why is `Y` a concrete type but both `Tuple{String,Real}` and

```julia
struct ABC
    a::String
    b::Real
end

```

are not? What is it about wrapping `Tuple{String,Real}` in a `NamedTuple` that makes it concrete?

I think believing `Y` was abstract initially led me to believe I could also construct a value of type `Z`.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [September 10, 2020, 10:44pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/5 "2020-09-10T22:44:30Z")

</div>

uhh…

```julia
julia> struct ABC
           a::String
           b::Real
       end

julia> isconcretetype(ABC)
true

```

I am not sure if the `Tuple`, however, is not kinda of special. Nor [tuple.jl](https://github.com/JuliaLang/julia/blob/master/base/tuple.jl), nor [ntuple.jl](https://github.com/JuliaLang/julia/blob/master/base/ntuple.jl) (both in the Julia source code) seem to really define the struct. Also, by my intuition these two should not be different:

```julia
julia> isconcretetype(Tuple{String,Real})
false

julia> struct MyTuple{A, B}; a :: A; b :: B; end

julia> isconcretetype(MyTuple{String, Real})
true

```

So there is nothing to do with `NamedTuple` actually, `Tuple` that seems to be the strange one.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [September 10, 2020, 11:18pm UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/6 "2020-09-10T23:18:44Z")

</div>

I have missed [this section of the manual](https://docs.julialang.org/en/v1/manual/types/#Tuple-Types) which says:

> However, there are three key differences:  
> […]  
> 2. Tuple types are _covariant_ in their parameters: `Tuple{Int}` is a subtype of `Tuple{Any}` . Therefore `Tuple{Any}` is considered an abstract type, and tuple types are only concrete if their parameters are.

So the `Tuple` type really is special. Different from other types that may have abstract type fields, `Tuple`s cannot do so.

---

<div class="post-metadata">

**Author:** ![Graham\_Gill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/graham_gill/32/9269_2.png) [@Graham\_Gill](https://discourse.julialang.org/u/Graham_Gill)\
**Post date:** [September 11, 2020, 3:44am UTC](https://discourse.julialang.org/t/dont-understand-behaviour-of-namedtuple-tuple-t-where-t/46382/7 "2020-09-11T03:44:50Z")

</div>

Great, thanks again. I realise what I did with `isconcretetype`: for `ABC` I mistakenly tested it on a value of type `ABC` rather than on the type `ABC` itself - `isconcretetype` then returns `false`, presumably because if the argument is not a type at all, it certainly can’t be a concrete type.
