# Type annotations in inner constructor

**URL:** <https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324>\
**Category:** New to Julia\
**Created:** [March 1, 2019, 12:13am UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324 "2019-03-01T00:13:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ckafi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckafi/32/7268_2.png) [@ckafi](https://discourse.julialang.org/u/ckafi)\
**Post date:** [March 1, 2019, 12:13am UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/1 "2019-03-01T00:13:49Z")

</div>

Hi there.  
In this struct want to enforce some invariants, so I check them with an inner constructor. But I also want to use all the type annotations. This leads to a lot of repetition, which is kind of ugly.

```julia
struct LRNData
    data::AbstractMatrix{Float64}
    column_types::AbstractArray{LRNCType, 1}
    keys::AbstractArray{T, 1} where T <: Integer
    names::AbstractArray{S, 1} where S <: AbstractString
    key_name::AbstractString
    comment::AbstractString

    function LRNData(
        data::AbstractMatrix{Float64},
        column_types::AbstractArray{LRNCType, 1},
        keys::AbstractArray{T, 1} where T <: Integer,
        names::AbstractArray{S, 1} where S <: AbstractString,
        key_name::AbstractString,
        comment::AbstractString
    )
        # ...
    end
end

```

Is there a more elegant way of doing this?  
Thanks.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [March 1, 2019, 12:26am UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/2 "2019-03-01T00:26:55Z")

</div>

Yes, remove all those abstract types 😃

At first sight that might sound like a laughable suggestion! But declaring abstract fields like `data::AbstractMatrix{Float64}` is unlikely to be very helpful for performance, as the compiler will still usually need to invoke generic dispatch when calling functions on the fields of `LRNData` (that is, abstract field types tend to defeat the devirtualization optimization which is very important to well performing julia code). If you do want performance, you’ll need to either make `LRNData` into a parametric type like `LRNData{T <: AbstractMatrix{Float64}, ...}` and have `data::T` in the body, or alternatively convert the input matrices into concrete types like `data::Matrix{Float64}` using the constructor.

Alternatively, if your type annotations are for documentation or safety and you don’t care about performance, you may declare them only once in the constructor and leave the field types completely generic.

If both those suggestions fail and you’re making a lot of `struct`s with the same type of code in the constructor you could consider a macro.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 1, 2019, 6:39am UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/3 "2019-03-01T06:39:48Z")

</div>

I think Chris’ post above says it all, but there’s also a good description in the manual, including many examples:

[https://docs.julialang.org/en/v1/manual/performance-tips/index.html#Type-declarations-1](https://docs.julialang.org/en/v1/manual/performance-tips/index.html#Type-declarations-1)

---

<div class="post-metadata">

**Author:** ![ckafi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckafi/32/7268_2.png) [@ckafi](https://discourse.julialang.org/u/ckafi)\
**Post date:** [March 1, 2019, 1:20pm UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/4 "2019-03-01T13:20:54Z")

</div>

Thank you both for the replies.

I see that all the abstract types might hamper performance. I think I don’t need them anyways.

But if I want performance **and** type safety, I need type annotations in both the fields and the constructor?

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [March 1, 2019, 2:25pm UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/5 "2019-03-01T14:25:43Z")

</div>

I’m still somewhat of a novice with the type system, but here is how I would approach the problem:

```julia
struct LRNCType
#stuff here
end

struct LRNData{T<:Int,S<:AbstractString}
    data::Array{Float64,2}
    column_types::Array{LRNCType,1}
    keys::Array{T,1} 
    names::Array{S,1} 
    key_name::String
    comment::String
end

data = rand(2,2)
ct = [LRNCType() for i in 1:2]
Keys = [1,2]
names = ["name1","name2"]
key_name = "name"
comment = "comment"
LRN = LRNData(data,ct,Keys,names,key_name,comment)

```

I think this makes the types concrete and therefore performant while providing the type safety check you need. For example, it will throw an error if you make Keys an array of Float64. There is no need to create a constructor with type annotations. Unless you are doing something specific, the default constructor should suffice.

---

<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:** [March 1, 2019, 2:54pm UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/6 "2019-03-01T14:54:36Z")

</div>

> [@ckafi](#):
>
> But if I want performance **and** type safety, I need type annotations in both the fields and the constructor?

Probably not. Having concretely typed fields in your struct is important for performance, but your function arguments don’t need concrete types to perform well. For example, something like this:

```julia
struct Foo
  x::Matrix{Float64}
  
  function Foo(x::AbstractMatrix)
     do_some_checking(x)
     new(x)
  end
end

```

will give excellent performance.

Another way of thinking about this is that functions (including constructors) are automatically specialized on the actual types of whatever _values_ you call them with (and every value always has a concrete type in Julia), while `struct`s use exactly whatever field types you used when you declare them (whether those are abstract or concrete).

---

<div class="post-metadata">

**Author:** ![ckafi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckafi/32/7268_2.png) [@ckafi](https://discourse.julialang.org/u/ckafi)\
**Post date:** [March 1, 2019, 7:59pm UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/7 "2019-03-01T19:59:19Z")

</div>

> [@Christopher\_Fisher](#):
>
> Unless you are doing something specific, the default constructor should suffice.

I’m enforcing some invariants for the struct, so I have to have a constructor that checks them at creation.

---

<div class="post-metadata">

**Author:** ![ckafi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckafi/32/7268_2.png) [@ckafi](https://discourse.julialang.org/u/ckafi)\
**Post date:** [March 1, 2019, 8:01pm UTC](https://discourse.julialang.org/t/type-annotations-in-inner-constructor/21324/8 "2019-03-01T20:01:34Z")

</div>

> [@rdeits](#):
>
> Another way of thinking about this is that functions (including constructors) are automatically specialized on the actual types of whatever _values_ you call them with (and every value always has a concrete type in Julia), while `struct` s use exactly whatever field types you used when you declare them (whether those are abstract or concrete).

Thanks, that’s very enlightening. I now de-abstracted (?) the types for the struct and some more generic types in the function definition.
