# 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:** 20\
**Page:** 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 18, 2022, 6:50pm UTC](https://discourse.julialang.org/t/field-types/81277/1 "2022-05-18T18:50:41Z")

</div>

I know that the following:

```nohighlight
struct test{T<:Real}
    a::T
    b::T
end

```

is better than:

```nohighlight
struct test
    a::Real
    b::Real
end

```

but why can’t I fully specify the field types like this:

```nohighlight
struct test{T::Float64}
    a::T
    b::T
end

```

Wouldn’t this allow the compiler to optimize better?

---

<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:** [May 18, 2022, 6:57pm UTC](https://discourse.julialang.org/t/field-types/81277/2 "2022-05-18T18:57:11Z")

</div>

I think you’re confusing optimization with how much typing you have to do. With your last example, you’ve effectively written:

```julia
struct test
    a::Float64
    b::Float64
end

```

That’s more typing, but it’s identical to what I think you want your example to mean so both would identical efficiency.

---

<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 18, 2022, 6:59pm UTC](https://discourse.julialang.org/t/field-types/81277/3 "2022-05-18T18:59:18Z")

</div>

Well now I’m confused about why my first example allows for better optimization over the second.

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [May 18, 2022, 7:05pm UTC](https://discourse.julialang.org/t/field-types/81277/4 "2022-05-18T19:05:27Z")

</div>

In the first example, `a` and `b` have to be of the same concrete type, whereas in the second example, `a` and `b` can be different concrete types (as long as they’re both subtypes of `Real`)

---

<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:** [May 18, 2022, 7:06pm UTC](https://discourse.julialang.org/t/field-types/81277/5 "2022-05-18T19:06:51Z")

</div>

Your first example creates an infinite family of types – one for each value of `T`. For example, when `T === Float64`, your first example creates the equivalent of:

```julia
struct test
    a::Float64
    b::Float64
end

```

Your second example instead is exactly:

```julia
struct test
    a::Real
    b::Real
end

```

So one type has concretely typed fields (of type `Float64`) and the other has non-concretely typed fields (of type `Real`).

---

<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 18, 2022, 7:13pm UTC](https://discourse.julialang.org/t/field-types/81277/6 "2022-05-18T19:13:29Z")

</div>

So the compiler doesn’t need to know what the exact concrete type is a priori, just which fields have the same concrete types

---

<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 18, 2022, 7:14pm UTC](https://discourse.julialang.org/t/field-types/81277/7 "2022-05-18T19:14:23Z")

</div>

No, the fact that there are two fields in this struct is a total distraction. The same problem is present in

```julia
struct test
    a::Real
end

```

which is different from

```julia
struct test{T <: Real}
    a::T
end 

```

---

<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:** [May 18, 2022, 7:15pm UTC](https://discourse.julialang.org/t/field-types/81277/8 "2022-05-18T19:15:52Z")

</div>

Depends what “a priori” means since Julia isn’t statically typed. In the sequence of lines of code below, the exact types are known when an object is created:

```julia
julia> struct test{T <: Real}
       a::T
       B::T
       end

julia> test(1.0, 2.0)
test{Float64}(1.0, 2.0)

```

---

<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 18, 2022, 7:17pm UTC](https://discourse.julialang.org/t/field-types/81277/9 "2022-05-18T19:17:06Z")

</div>

I strongly recommend reading [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Composite-Types) and [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Parametric-Types)

---

<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 18, 2022, 7:17pm UTC](https://discourse.julialang.org/t/field-types/81277/10 "2022-05-18T19:17:39Z")

</div>

I have. I’ll re-read it though.

---

<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 18, 2022, 7:18pm UTC](https://discourse.julialang.org/t/field-types/81277/11 "2022-05-18T19:18:53Z")

</div>

So for the following struct:

```nohighlight
struct NS
    nParticles:: Int64
    setSize:: Int64
    l:: Int64
    boxSize:: Float64
    energies:: Array{Float64,1}
    activeSet:: Array{SVector{2,Float64},2}

end

```

should be re-written to:

```nohighlight
struct NS{T <: Real,S <: Real}
    nParticles:: T
    setSize:: T
    l:: T
    boxSize:: S
    energies:: Array{S,1}
    activeSet:: Array{SVector{2,S},2}

```

end

---

<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:** [May 18, 2022, 7:20pm UTC](https://discourse.julialang.org/t/field-types/81277/12 "2022-05-18T19:20:53Z")

</div>

There is no efficiency gain from that change, you’ve just increased the number of valid types that can be bound to `T` and `S`. The first example is also somewhat broken: you have `T` and `S` parameters, but they’re never used.

---

<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 18, 2022, 7:21pm UTC](https://discourse.julialang.org/t/field-types/81277/13 "2022-05-18T19:21:50Z")

</div>

So basically what’s going on here is that when you have

```julia
struct test
    a::Real
end

```

then any time julia wants to look inside a `test` object, it has no idea what it’s going to get out, all it knows is that the data it gets will be a subtype of `Real`, but subtypes of `Real` could have **any** memory layout imaginable, and any set of methods defined for them, so there are essentially no optimizations that can be performed until Julia actually unpacks the struct itself and looks at the concrete type.

On the other hand, when you write

```julia
struct Test{T <: Real}
    a::T
end

```

then a `Test(1)` has a different type from a `Test(1.0)` (that is, `Test{Int}` vs `Test{Float64}`) and that information can be used to do concrete optimizations because the memory layout is thus fixed forever, and the methods on `Int` and `Float64` are fixed in a given worldage.

---

<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 18, 2022, 7:25pm UTC](https://discourse.julialang.org/t/field-types/81277/14 "2022-05-18T19:25:25Z")

</div>

Writing

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

```

can basically just be thought of as convenient syntax for writing

```julia
struct TestInt
    a::Int
end
struct TestFloat64
   a::Float64
end
struct TestReal
   a::Real
end
...

```

for every single possible subtype of `Real`. The parameters basically just let us easily define a group of implicitly defined types. `Test{Int}` and `TestInt` have all the same properties, `Test{Int}` is just easier to work with.

---

<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 18, 2022, 7:46pm UTC](https://discourse.julialang.org/t/field-types/81277/15 "2022-05-18T19:46:32Z")

</div>

So what is the proper way to build this struct?

---

<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 18, 2022, 8:02pm UTC](https://discourse.julialang.org/t/field-types/81277/16 "2022-05-18T20:02:33Z")

</div>

That depends entirely on what you want it to hold. Do you only want to store Float64 data? then your first example is fine (once you remove the unnecessary type parameters). Do you want to be able to efficiently store any types `T <: Real` and `S <: Real`? Then use the second.

---

<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:21pm UTC](https://discourse.julialang.org/t/field-types/81277/18 "2022-05-20T16:21:45Z")

</div>

But in the second case the types of the fields can be inferred from the type of the wrapper object (from performance tips in the manual).

---

<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:22pm UTC](https://discourse.julialang.org/t/field-types/81277/19 "2022-05-20T16:22:53Z")

</div>

So even

```nohighlight
struct test{T}
    a::T
end

```

would be better than:

```nohighlight
struct test
    a::Float64
end

```

right?

---

<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:** [May 20, 2022, 4:30pm UTC](https://discourse.julialang.org/t/field-types/81277/20 "2022-05-20T16:30:14Z")

</div>

No. There are two orthogonal concepts here:

1. Using a parametric type instead of manually creating multiple similar types.
2. Minimizing the use of abstract types for efficiency.

Let’s consider three code options:

Option A: Manually write out multiple types

```julia
struct TestInt64
    a::Int64
end

struct TestFloat64
   a::Float64
end

```

Option B: Use a parametric type

```julia
struct Test{T <: Real}
    a::T
end

```

Option C: Use a single type with abstract fields

```julia
struct Test
    a::Real
end

```

There is no difference in efficiency between A and B – the question is whether you create a lot of redundant types or a single parametric type.

There is an efficiency improvement between B and C – for any given type under `Real`, B creates a new “customized” struct type that has a concrete field, whereas C reuses the same inefficient struct type every time.

---

<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:30pm UTC](https://discourse.julialang.org/t/field-types/81277/21 "2022-05-20T16:30:55Z")

</div>

It’s ‘better’ in that it can store any type. But if you’re only wanting to strore `Float64`, then it’s the exact same.

That is, if you have

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

struct Test2
    a::Float64
end

```

then `Test1(1.0)` is basically the exact same thing as `Test2(1.0)`.

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