# Field types

**URL:** https://discourse.julialang.org/t/field-types/81277
**Category:** New to Julia
**Tags:** struct
**Created:** [May 18, 2022, 6:50pm UTC](https://discourse.julialang.org/t/field-types/81277 "2022-05-18T18:50:41Z")
**Posts on this page:** 10
**Page:** 2

<div class="post-metadata">

### Author: ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)
#### Post date: [May 20, 2022, 4:40pm UTC](https://discourse.julialang.org/t/field-types/81277/22 "2022-05-20T16:40:59Z")

</div>

Hmmm, but in my first example, when I get an instance of the object and check its type

```nohighlight
m = test(5.2)
typeof(m) # yields test{Float64}

```

but in my second example `typeof(m)` just yields `test`. Maybe I understood this explanation in “perfromance tips” incorrectly but I thought that meant that the first example is preferred over the second for optimization purposes.

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [May 20, 2022, 4:53pm UTC](https://discourse.julialang.org/t/field-types/81277/23 "2022-05-20T16:53:23Z")

</div>

I think that what’s confusing you here is that you’ve written two types with the same name. Name them `Test1{T}` and `Test2`.

```julia
struct Test1{T}
    a::T
end 

struct Test2
    a::Float64
end

```

Now, if I have an object of type `Test2` I always know that the `a` field is of type `Float64`.

```julia
julia> let t = Test2(1.0)
           @code_typed t.a
       end
CodeInfo(
1 ─ %1 = Base.getfield(x, f)::Float64
└── return %1
) => Float64

```

---

<div class="post-metadata">

### Author: ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)
#### Post date: [May 20, 2022, 4:59pm UTC](https://discourse.julialang.org/t/field-types/81277/24 "2022-05-20T16:59:41Z")

</div>

This is my exact code

```nohighlight
struct Test1
    a:: Float64
end

struct Test2{T}
    a::T
end
a = Test1(5.5)
b = Test2(5.5)
typeof(a) #yields Test1
typeof(b) #yields Test2{Float64}

```

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [May 20, 2022, 5:02pm UTC](https://discourse.julialang.org/t/field-types/81277/25 "2022-05-20T17:02:06Z")

</div>

Good. So what we’re telling you is that there is no performance difference between operating on `a` vs `b`, because all the same information is available to the compiler.

E.g. these methods have identical typed IR

```julia
julia> f(t) = t.a + 1.0

julia> code_typed(f, (Test1{Float64},))
1-element Vector{Any}:
 CodeInfo(
1 ─ %1 = Base.getfield(t, :a)::Float64
│ %2 = Base.add_float(%1, 1.0)::Float64
└── return %2
) => Float64

julia> code_typed(f, (Test2,))
1-element Vector{Any}:
 CodeInfo(
1 ─ %1 = Base.getfield(t, :a)::Float64
│ %2 = Base.add_float(%1, 1.0)::Float64
└── return %2
) => Float64

```

---

<div class="post-metadata">

### Author: ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)
#### Post date: [May 20, 2022, 5:10pm UTC](https://discourse.julialang.org/t/field-types/81277/26 "2022-05-20T17:10:17Z")

</div>

So what am I not understanding about the following portion of the documentation:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/a/1a709a68ee62df3c78a3ec31a4be61587916c25a.jpeg)

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [May 20, 2022, 5:47pm UTC](https://discourse.julialang.org/t/field-types/81277/27 "2022-05-20T17:47:39Z")

</div>

The difference is that `Float64` is a concrete type! `AbstractFloat` is an abstract type, so the compiler has no clue what could actually be stored there just based on type information. The data could have any layout.

With a `Float64` is knows **exactly** what is stored.

---

<div class="post-metadata">

### Author: ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)
#### Post date: [May 20, 2022, 5:54pm UTC](https://discourse.julialang.org/t/field-types/81277/28 "2022-05-20T17:54:21Z")

</div>

Consider the following code:

```julia
struct Type1 # No type parameter, but concrete field type
    a::Float64
end

struct Type2{T<:Real} # Type parameter
    a::T
end

struct Type3 # No type parameter, abstract field type
    a::Real
end

function f(x)
    return x.a + 1
end

x1 = Type1(1.0)
x2 = Type2(1.0)
x3 = Type3(1.0)

```

When calling `f` with either of `x1`, `x2`, or `x3`, compilation will occur. In this case, compilation involves figuring out the appropriate method of `+` to call, which depends on the type of `x.a`.

When `f(x1)` is called, the compiler can directly insert the code for the correct method `+(::Float64, ::Int)` because the type of `x1.a` is known from the type of `x1` (i.e., `x1` has type `Type1`, which has a field `a` of type `Float64`).

Similarly, when `f(x2)` is called, the compiler can directly insert the code for the correct method `+(::Float64, ::Int)` because the type of `x2.a` is known from the type of `x2` (i.e., `x2` has type `Type2{Float64}`, which has a field `a` of type `Float64` – the same as the type parameter).

In contrast, when `f(x3)` is called, the compiler _cannot_ directly insert the code for the correct method `+(::Float64, ::Int)` because the type of `x3.a` is _not_ known from the type of `x3`. Running `typeof(x3.a)` yields `Float64`, but this is a runtime check, not a compile time certainty; in this case, the type of `x3.a` is determined by the _value_ of `x3` (known at runtime), not from the _type_ of `x3` (known at compile time). In this case, dynamic dispatch must be used to select the correct method of `+` to use, resulting in worse performance.

---

<div class="post-metadata">

### Author: ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)
#### Post date: [May 20, 2022, 5:55pm UTC](https://discourse.julialang.org/t/field-types/81277/29 "2022-05-20T17:55:27Z")

</div>

Ah. I think you might be right. That might be the source of all of my confusion: abstract types. So I really shouldn’t use the output of `typeof` as an optimization check I guess. The wording in the manual seemed to indicate that maybe I should.

---

<div class="post-metadata">

### Author: ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)
#### Post date: [May 20, 2022, 6:06pm UTC](https://discourse.julialang.org/t/field-types/81277/30 "2022-05-20T18:06:45Z")

</div>

> [@lancejnelson](#):
>
> ```julia
> struct Test1
> a:: Float64
> end
> 
> struct Test2{T}
> a::T
> end
> a = Test1(5.5)
> b = Test2(5.5)
> typeof(a). #yields Test1
> typeof(b). #yields Test2{Float64}
> 
> ```

`typeof(a)` and `typeof(b)` here do not tell you anything about performance of those types. `Test1` and `Test2{Float64}` are essentially just the names of the structs (a.k.a. types) you defined. In the `Test3` example below, I get the same output from `typeof` as your `Test2`, but `Type3` will perform badly because 2/3 of the fields are abstractly typed.

```julia
julia> struct Test3{T}
           a::Real
           b::T
           c::AbstractString
       end

julia> c = Test3(5.5, 5.6, "hello")
Test3{Float64}(5.5, 5.6, "hello")

julia> typeof(c)
Test3{Float64}

```

The point is that you want the _fields_ of your struct to have concrete types (not abstract types). If you only need to allow `Float64`, then it is fine to assign that type to a field directly. Parametric types allow the definition of multiple concrete types at once. The example below will be concretely typed parametrically.

```julia
julia> struct Test4{T}
           a::T
           b::T
           c::String
       end

julia> Test4(5.5, 5.6, "hello")
Test4{Float64}(5.5, 5.6, "hello")

julia> Test4("hello", "welcome", "home")
Test4{String}("hello", "welcome", "home")

```

The struct `Test5` below is exactly the same as `Test4` above except that `Test5` will error if I try to enter something other than a subtype of `Real` for the first two fields. There is no performance difference.

```julia
julia> struct Test5{T <: Real}
           a::T
           b::T
           c::String
       end

julia> Test5(5.5, 5.6, "hello")
Test5{Float64}(5.5, 5.6, "hello")

julia> Test5("hello", "welcome", "home")
ERROR: MethodError: no method matching Test5(::String, ::String, ::String)
Closest candidates are:
  Test5(::T, ::T, ::String) where T<:Real at REPL[12]:2
Stacktrace:
 [1] top-level scope
   @ REPL[14]:1

```

---

<div class="post-metadata">

### Author: ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)
#### Post date: [May 20, 2022, 6:08pm UTC](https://discourse.julialang.org/t/field-types/81277/31 "2022-05-20T18:08:59Z")

</div>

Thank you. (to everyone!!). It’s starting to come together.

[Previous page](https://discourse.julialang.org/t/field-types/81277.md?page=1)
