# Infer type from tuple argument

**URL:** <https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294>\
**Category:** General Usage\
**Created:** [October 6, 2017, 4:32pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294 "2017-10-06T16:32:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [October 6, 2017, 4:32pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/1 "2017-10-06T16:32:33Z")

</div>

Hi all,  
I have been having problems making my functions type stable as I don’t entirely understand how it works.  
I managed to make most of my functions type stable (I think) but I am having problems with the most performance sensitive one. I believe the problem has to do with the fact that I decided to use multiple dispatch and one of the outputs is an array with different size depending on what type it is fed with.  
I tried to build a minimal working example of my problem. In my code I am doing more complicated things in the `iterator` function, calling all sorts of other user-defined functions, but I do have a `max` operator in there and I believe that’s where the problems start.  
Here’s the MWE:

```julia
abstract type Agent end
abstract type Entr <: Agent end
abstract type Work <: Agent end
immutable Ye <: Entr end
immutable Yw <: Work end
immutable Oe <: Entr end
immutable Ow <: Work end

mutable struct Dimensions
    x_dim::Int64
    y_dim::Int64
    z_dim::Int64
end

mutable struct Household  
    h_type::Agent
    dim::Dimensions

    V::Array{Float64,N} where {N}
    pol_tuple::NTuple{N,Array{Float64}} where {N}
end

function Dimensions()
    x_dim = 10; y_dim = 2; z_dim = 2
    return Dimensions(x_dim,y_dim,z_dim)
end
D = Dimensions()

function Household( h_type::Agent;
                    dim::Dimensions = D)
    
    function initiate(h_type::Ye)
        V = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)
        a = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)
        c = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)

        return V::Array{Float64,3}, (a,c)
    end

    function initiate(h_type::Yw)
        V = ones(Float64,dim.x_dim,dim.y_dim)
        k = ones(Float64,dim.x_dim,dim.y_dim)
        c = ones(Float64,dim.x_dim,dim.y_dim)

        return V::Array{Float64,2}, (k,c)
    end

    (V, pol_tuple) = initiate(h_type)

    return Household(h_type,dim,V,pol_tuple)
end

function iterator!(hs::NTuple{N,Household} where {N})

    (hye,hyw) = hs
    Vye = similar(hye.V::Array{Float64,3})
    Vyw = similar(hyw.V::Array{Float64,2})
    
    Vye = max.(2.0*rand(hye.dim.x_dim,hye.dim.y_dim,hye.dim.y_dim)-1.0,hye.V::Array{Float64,3})
    Vyw = max.(2.0*rand(hye.dim.x_dim,hye.dim.y_dim),hyw.V::Array{Float64,2})

    hye.V::Array{Float64,3} = Vye::Array{Float64,3}
    hyw.V::Array{Float64,2} = Vyw::Array{Float64,2}
end

hye = Household(Ye())
hyw = Household(Yw())
iterator!((hye,hyw))

```

Looking at the output of `@code_warntype` I see many issues, the biggest of which seems to be that, when it tries to get the `:V` field of either `hyw` or `hye`, it does not know what’s its size.  
I suspect the problem here is that both are the outcome of the initiate function, which outputs differently sized arrays depending on whether the type is `::Yw` or `::Ye`.

Also, if you have any sorts of general performance suggestions they are very well appreciated!  
Thanks a lot in advance.

---

<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:** [October 6, 2017, 4:38pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/2 "2017-10-06T16:38:00Z")

</div>

This is a really big example, can you please try to find a minimal example that reproduces your problem?

In the meanwhile, there’s one issue I can see in your code:

```julia
mutable struct Household  
    h_type::Agent
    dim::Dimensions

    V::Array{Float64,N} where {N}
    pol_tuple::NTuple{N,Array{Float64}} where {N}
end

```

You have ~~two~~ (edit: three, see reply below) non-concretely typed fields including `V` and `pol_tuple`. This means that _every_ Household object must be able to hold _any_ number of dimensions in `V`. That’s probably not what you want, and it’s definitely going to cause performance issues. See: [https://docs.julialang.org/en/latest/manual/performance-tips/#Avoid-fields-with-abstract-type-1](https://docs.julialang.org/en/latest/manual/performance-tips/#Avoid-fields-with-abstract-type-1)

The common solution to this kind of problem is to make a parameterized type:

```julia
struct Household{N}
  V::Array{Float64, N}
end

```

or, even more flexibly:

```julia
struct Household{T <: Real, N}
  V::Array{T, N}
end

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 6, 2017, 4:39pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/3 "2017-10-06T16:39:39Z")

</div>

Try

```julia
mutable struct Household{A <: Agent, N}   
    h_type::A
    dim::Dimensions

    V::Array{Float64,N}
    pol_tuple::NTuple{N,Array{Float64}}
end

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 6, 2017, 4:40pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/4 "2017-10-06T16:40:17Z")

</div>

`Agent` is also abstract.

---

<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:** [October 6, 2017, 4:47pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/5 "2017-10-06T16:47:37Z")

</div>

Ah, good point, thanks.

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [October 6, 2017, 7:03pm UTC](https://discourse.julialang.org/t/infer-type-from-tuple-argument/6294/6 "2017-10-06T19:03:16Z")

</div>

Ah, ok! Got it. It makes sense now.

Thanks a lot!
