# Inner constructors with parametric types, can't seem to get them to work for me

**URL:** https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337
**Category:** General Usage
**Tags:** question
**Created:** [November 21, 2019, 7:29am UTC](https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337 "2019-11-21T07:29:16Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![tlnagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlnagy/32/5815_2.png) [@tlnagy](https://discourse.julialang.org/u/tlnagy)
#### Post date: [November 21, 2019, 7:29am UTC](https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337/1 "2019-11-21T07:29:16Z")

</div>

Say I have a type that looks the following:

```julia
julia> struct Test{T, N, A} <: AbstractArray{T, N}
           a::Dict{NTuple{N, Int}, String}
           b::Type{T}
           c::A
           d::Array{T, 2}

           function Test{T, N, A}(a, b, c) where {T, N, A}
               new(a, b, c, Array{T}(undef, 10, 10))
           end
       end

```

I try instantiating it and get a method error

```julia
julia> Test(Dict((1,2,3,4)=>"test"), Float64, 6)
ERROR: MethodError: no method matching Test(::Dict{NTuple{4,Int64},String}, ::Type{Float64}, ::Int64)
Stacktrace:
 [1] top-level scope at REPL[3]:1

```

However, an almost identical type with no inner constructor works as I expect:

```julia
julia> struct Test2{T, N, A} <: AbstractArray{T, N}
           a::Dict{NTuple{N, Int}, String}
           b::Type{T}
           c::A
           d::Array{T, 2}
       end

julia> Test2(Dict((1,2,3,4)=>"test"), Float64, 6, Array{Float64}(undef, 10, 10));

```

Why is this happening? I’m not use I grok the difference and the [Julia docs](https://docs.julialang.org/en/v1/manual/constructors/#Parametric-Constructors-1) didn’t clear it up for me.

I would like to use the first approach because the field `d` is a cache that is automatically created and users shouldn’t have to deal with it.

EDIT: Using Julia 1.2

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 21, 2019, 7:39am UTC](https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337/2 "2019-11-21T07:39:58Z")

</div>

Your inner constructor defines a method with type parameters in the signature (the `{ ... }` part). Unless you really need it, I would recommend just using types from the call signature. Also, you don’t need to store the type `T` in a slot `b` explicitly. I would do something like this instead:

```julia
struct Test{T, N, A} <: AbstractArray{T, N}
    a::Dict{NTuple{N, Int}, String}
    c::A
    d::Array{T, 2}
    function Test(::Type{T}, a::Dict{NTuple{N,Int},String}, c::A) where {T, N, A}
        new{T,N,A}(a, c, Array{T}(undef, 10, 10))
    end
end

# this works, but printing fails because you need to define a method 
# for `getindex` and `size` so that # `show` works, or alternatively 
# define the latter
z = Test(Float64, Dict((1,2,3,4)=>"test"), 6);

```

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [November 21, 2019, 1:47pm UTC](https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337/3 "2019-11-21T13:47:49Z")

</div>

As @Tamas_Papp said, your inner constructor has type parameters in `{}` in its signature, so you have to call it with those parameters specified at the call site:

```julia
julia> Test{Int, 1, Int}(Dict(), Int, 1)

```

(note that trying to display the result fails because your type claims to be an `AbstractArray` but doesn’t implement `size()` or `getindex()`).

The reason you don’t usually have to do this is that if you do not define an inner constructor, Julia does it for you. For example, if you have a type like:

```julia
julia> struct Foo{T}
        x::T
      end

```

then Julia automatically defines a default inner constructor which looks something like:

```julia
Foo(x::T) where {T} = new{T}(x)

```

But if you define an inner constructor, then it _replaces_ that default. So you might want to do something like:

```julia
julia> struct Bar{T}
         x::T
         function Bar{T}(x) where {T}
           println("inner constructor stuff goes here")
           new{T}(x)
         end
       end

       # This is the constructor which gets called when you do Bar(...)
       # instead of Bar{T}(...)
       Bar(x::T) where {T} = Bar{T}(x)
Bar

julia> Bar(1)
inner constructor stuff goes here
Bar{Int64}(1)

julia> Bar{Float64}(1)
inner constructor stuff goes here
Bar{Float64}(1.0)

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 21, 2019, 1:56pm UTC](https://discourse.julialang.org/t/inner-constructors-with-parametric-types-cant-seem-to-get-them-to-work-for-me/31337/4 "2019-11-21T13:56:13Z")

</div>

Incidentally, I don’t think an explicitly parametric constructor is a common use case for most composite types that don’t contain extra parameters that are not obtainable from the arguments. In the case above, a

```julia
Test{T}(a, c)

```

constructor might make sense though.
