# How to define outer constructor based on array size?

**URL:** <https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193>\
**Category:** General Usage\
**Created:** [December 29, 2016, 1:46am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193 "2016-12-29T01:46:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 1:46am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/1 "2016-12-29T01:46:55Z")

</div>

Consider the parametric type below:

```julia
immutable Foo{N}
  A::AbstractMatrix{Float64}
  b::AbstractVector{Float64}

  Foo(A,b) = size(A) == (N,length(b)) ? new(A,b) : error("incorrect size")
end

```

Because I defined the inner constructor, I can do:

```julia
Foo{3}(eye(3),ones(3)) # works
Foo{2}(eye(3),ones(3)) # fails as expected

```

but I cannot do:

```julia
Foo(eye(3),ones(3)) # fails but I would like it to work

```

How to solve this problem?

---

<div class="post-metadata">

**Author:** ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)\
**Post date:** [December 29, 2016, 1:52am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/2 "2016-12-29T01:52:17Z")

</div>

That is because you provide no means to promote the number of rows to the type-parameter `N`, thus the constructor does not know what `N` is supposed to be.

You could create an outer constructor to do that promotion

```julia
Foo(A,b) = Foo{size(A,1)}(A,b)

```

```nohighlight
julia> Foo(eye(3),ones(3))
Foo{3}([1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0],[1.0,1.0,1.0])

```

Note, however, that this kind of value promotion to a type parameter poisons the type-inference, since the value is not known at compile-time, but instead evaluated at runtime.  
see `@code_warntype Foo(eye(3),ones(3))`

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 2:09am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/3 "2016-12-29T02:09:49Z")

</div>

@Evizero thank you for the clear answer. Is there any trick for exposing the actual size of the array to the type system?

---

<div class="post-metadata">

**Author:** ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)\
**Post date:** [December 29, 2016, 2:15am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/4 "2016-12-29T02:15:40Z")

</div>

Well in your case using `Foo{3}(eye(3),ones(3))` would be the trick. More generally you could consider using [https://github.com/JuliaArrays/StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) if it fits your purposes.

Other than that the type-inference “issue” may not be an issue at all depending on your use case.  
In my personal experience type-stability turned out to either be a huge issue or absolutely none at all.  
My advice: Ask yourself how often and where this code will be executed. If the answer is “a few times in the top level scope of my script” then chances are you won’t notice its influence. However, if this code is to be executed in some inner function that is called very often, then it is likely a problem that should be redesigned.

In other words: make sure that the functions that are doing the heavy computations are themself type-stable. If that is the case, the it may not matter so much that they are invoked using dynamic dispatch (which would be the consequence when calling a function with the result of `Foo(eye(3),ones(3))`) . The key is benchmarking your code before trying to optimize it.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 29, 2016, 3:54am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/5 "2016-12-29T03:54:37Z")

</div>

> [@juliohm](#):
>
> A::AbstractMatrix{Float64}

That is not a concrete type. You probably want stricter typing on your types. This right here would be the cause of type-instabilities and inference issues.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 9:49am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/6 "2016-12-29T09:49:43Z")

</div>

Thank you @ChrisRackauckas, I will keep this in mind. Ideally I would like to have generic matrices that could be stored arbitrarily on disk, sparse, etc, but if that is a big bottleneck, I will use a concrete type.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 30, 2016, 5:24am UTC](https://discourse.julialang.org/t/how-to-define-outer-constructor-based-on-array-size/1193/7 "2016-12-30T05:24:24Z")

</div>

The best way of having concrete types for those fields of your type, is to use parameterization.  
That way, you can have all the flexibility of being able to use different types (such as structures backed up on disk, or sparse, or both [my specialty! ;-)]), but still have all of the advantages of using concrete types, as @ChrisRackauckas pointed out.
