# Annotating Types: Best practice for beginners

**URL:** <https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521>\
**Category:** New to Julia\
**Created:** [November 21, 2020, 1:19am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521 "2020-11-21T01:19:28Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![s0916314](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@s0916314](https://discourse.julialang.org/u/s0916314)\
**Post date:** [November 21, 2020, 1:19am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/1 "2020-11-21T01:19:28Z")

</div>

As a beginner I’m slightly unsure of when I should be annotating my code with types. I’ve read the section on types in the Julia manual and I’m happy with the basics (type hierarchy, parametric types, avoiding abstract types, and the importance of type stability) but I’m still slightly unsure how I should using type annotations in practice.

For instance, from the QuantEcon website:

> You will notice that in the lecture notes we have never directly declared any types. This is intentional both for exposition and as a best practice for using packages (as opposed to writing new packages, where declaring these types is very important). It is also in contrast to some of the sample code you will see in other Julia sources, which you will need to be able to read. To give an example of the declaration of types, the following are equivalent. While declaring the types may be verbose, would it ever generate faster code? The answer is almost never.

```julia
function f(x, A)
    b = [5.0, 6.0]
    return A * x .+ b
end

val = f([0.1, 2.0], [1.0 2.0; 3.0 4.0])

```

```julia
function f2(x::Vector{Float64}, A::Matrix{Float64})::Vector{Float64}
    # argument and return types
    b::Vector{Float64} = [5.0, 6.0]
    return A * x .+ b
end

val = f2([0.1; 2.0], [1.0 2.0; 3.0 4.0])

```

However, I have seen other sources that suggest that annotating code with type information is the key to performance in Julia. For instance, I’m told that if I preallocate a vector I should always include type information.

I’m sure there’s a lot I’m not fully understanding but If someone could provide some tips or general guidance on these issues, it would be very helpful for beginners like me.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [November 21, 2020, 1:49am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/2 "2020-11-21T01:49:58Z")

</div>

- Annotate types inside of type definitions for performance.
- Annotate types inside of function definitions to exploit multiple dispatch or to prevent duck typing.

Basically, this is good for performance:

```julia
struct Foo
    x::Int64
    y::Float64
end

```

And this is bad:

```julia
struct Foo
    x
    y
end

```

In contrast, performance is the same for either of these when called on `z` of type `Foo`:

```julia
function bar(z)
    z.x + z.y
end

```

```julia
function bar(z::Foo)
    z.x + z.y
end

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 21, 2020, 3:06am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/3 "2020-11-21T03:06:10Z")

</div>

> [@johnmyleswhite](#):
>
> ```julia
> struct Foo
> x::Int64
> y::Float64
> end
> 
> ```

Adding to this, it’s also equally fast using parametric types like this, instead of explicit types :

```julia
struct Foo{X,Y}
    x::X
    y::Y
end

```

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [November 21, 2020, 10:55am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/4 "2020-11-21T10:55:30Z")

</div>

> [@s0916314](#):
>
> For instance, I’m told that if I preallocate a vector I should always include type information.

Well, yes and no.  
Yes, it is important to preallocate a vector with a concrete element type for performance.  
However, you can do it without specifying the argument types in many cases, as there are helper functions:  
`similar(x)` - creates an uninitialized array with the same type and the same dimensions as `x`  
`typeof(x)` - returns the type of `x`, can be used as a constructor  
`eltype(x)` - returns the type of elements in `x`.

For example, those expressions are equivalent for an `x::Vector{Float64}`:

```julia
#1
y = Vector{Float64}(undef, length(x))

#2
y = typeof(x)(undef, length(x))

#3
y = similar(x)

#4
y = resize!(eltype(x)[], length(x))

```

In my personal opinion, it is good to use type annotations, but usually you shouldn’t specify _concrete_ types. E.g., `foo(x::Vector{Float64})` is typically not what you want, `foo(x::AbstractVector{<:Real})` is more like it. And when the number of arguments is greater than 2, you can easily see why one is encouraged to not use type annotations at all 🙂

It is also worth noting that typing in Julia is not the same as typing in C++. In C++, `foo(int n)` happily accepts all types for `n` which it can convert into `int` (i.e., `long`, `char`, `size_t`, even `float` are all fine, although you may opt into having a warning for the last case). In Julia, `foo(n::Int64)` means only `Int64`s are allowed, no `Int32`s, `BigInt`s, `UInt8`s etc. As such, annotating function arguments with concrete types might not even reflect the programmer’s intent properly.

---

<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, 2020, 11:25am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/5 "2020-11-21T11:25:19Z")

</div>

> [@Vasily\_Pisarev](#):
>
> E.g., `foo(x::Vector{Float64})` is typically not what you want, `foo(x::AbstractVector{<:Real})` is more like it

Note that both may be too restrictive if the code is intended to work with eg

```julia
Union{Missing,Int}[1,2,3]

```

or similar, which can easily happen in practice.

It is better not to rely on container element types for _dispatch_, except possibly for optimized versions which do the same thing.

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [November 21, 2020, 11:58am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/6 "2020-11-21T11:58:24Z")

</div>

Side-note: as a Julia beginner I find the answers and examples given here extremely useful! I would love to see more of these kinds of questions and responses in the manual or faq.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [November 21, 2020, 1:02pm UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/7 "2020-11-21T13:02:12Z")

</div>

A great first step would be for some intrepid member of the community to categorize all the questions on the forum each month, track the most frequently asked and make sure the best answers to those end up in a special doc. 🙂

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [November 21, 2020, 1:48pm UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/8 "2020-11-21T13:48:45Z")

</div>

To add on, if you have `Vector` as a type parameter in a function, you can’t use `skipmissing` either, which can be frustrating.

Unless you are using things which you _need_ a vector for, you should avoid specifying the container type.

---

<div class="post-metadata">

**Author:** ![s0916314](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@s0916314](https://discourse.julialang.org/u/s0916314)\
**Post date:** [November 21, 2020, 5:56pm UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/9 "2020-11-21T17:56:38Z")

</div>

I completely agree!

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [November 23, 2020, 12:24am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/10 "2020-11-23T00:24:39Z")

</div>

This is one of the rare situations where I think my view is different to most people here, so follow my advice at your own risk 🙂

I personally like to include type annotations on both the inputs and outputs to most of the code I write. This is for the simple reason that I find that when I come back and look at a piece of code three months later, the type annotations are very helpful in reminding my brain how a particular bit of code is structured.

It is worth emphasizing that a lot of the code I write is just for me, so keeping things as general as possible for the sake of others who might use my code is less of a priority. Having said that, I do have a few registered statistical packages, and even in those packages I always include annotations, albeit I’ve gone to some effort to make sure the annotations are as general as possible, and (for example) allow for things like `Missing` when working with number types.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 26, 2020, 9:16am UTC](https://discourse.julialang.org/t/annotating-types-best-practice-for-beginners/50521/11 "2020-11-26T09:16:33Z")

</div>

One aspect I find relevant is to think about the way code will error given different inputs. Sometimes the author assumes inputs will be of a certain type, then I think it should be type annotated. Any other type working with that function would be accidental, and errors with other types could possibly happen way later in the stack. This can lead to frustrating bugs.

When someone writes a generic function, I then think it’s again important to check the generic assumptions with meaningful error messages if they aren’t met. For example checking if some type can be iterated, or its length is known or it’s a bits type. Those can be traits sometimes.

Anyway, my point is, the more generic a pipeline, and the less assumptions are checked in the code with meaningful explanatory error messages, the more likely you are to hit bugs deep down the stack without knowing that you violated an implicit assumption further up.
