# Creating an Alias for a Struct Field

**URL:** <https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873>\
**Category:** General Usage\
**Created:** [July 10, 2024, 1:27pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873 "2024-07-10T13:27:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Maddy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maddy/32/210658_2.png) [@Maddy](https://discourse.julialang.org/u/Maddy)\
**Post date:** [July 10, 2024, 1:27pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/1 "2024-07-10T13:27:37Z")

</div>

I am trying to create a Particle `Struct`.  
I was wondering if there is a way to have `particle.pos` reference `particle.position` as an alias

Is there any way to have such a behaviour? I might set `pos` as another _field_ but then how would it change if say I mutate `position`

```julia
mutable struct Particle
    position
    #pos 
end

```

Is it something computationally light? (Is observables light?)

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [July 10, 2024, 1:58pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/2 "2024-07-10T13:58:25Z")

</div>

Using the dot syntax to access fields of a struct are converted into calls to `getproperty` and `setproperty!` so you could just define these.

```julia
getproperty(p::Particle, sym) = getfield(p, sym === :pos ? :position : sym)
setproperty!(p::Particle, sym, x) = setfield!(p, sym === :pos ? :position : sym, x)

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 10, 2024, 2:11pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/3 "2024-07-10T14:11:44Z")

</div>

`position(p :: Particle) = p.pos` would be idiomatic.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [July 10, 2024, 2:17pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/4 "2024-07-10T14:17:39Z")

</div>

I think you have to define `getproperty(p::Particle, sym::Symbol)` as otherwise you’ll get an ambiguity error.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [July 10, 2024, 2:29pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/5 "2024-07-10T14:29:23Z")

</div>

To get tab-completion you should also define `propertynames`.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [July 10, 2024, 2:46pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/6 "2024-07-10T14:46:14Z")

</div>

I’ll echo an above post advocating that, while modifying `getproperty` is possible, an accessor function like `pos(p::Particle)` or `position(p::Particle)` is often nicer (in my experience).

If `.position` is too long, you could always just name the field `pos` to begin with.

* * *

As a rather significant tangent, and without knowing what it is you’re doing, I find that a `struct` (rather than `mutable struct`) is often much more convenient (and sometimes more performant) for these (and most) sorts of objects. Rather than mutate a `Particle`, it’s often just as fast to generate an entirely new one with most of the fields copied from the previous. The compiler is pretty good at this and might _choose_ to mutate the old one anyway, if the old one is not needed any more (and if the old one still is needed, then mutating it to produce the new one is going to be a problem).

I’ll also recommend you use `SVector` (probably `SVector{3,Float64}`) from StaticArrays.jl for the position field. Note that this is also immutable, which slightly changes how one interacts with it compared to `Vector{Float64}`.

---

<div class="post-metadata">

**Author:** ![Maddy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maddy/32/210658_2.png) [@Maddy](https://discourse.julialang.org/u/Maddy)\
**Post date:** [July 10, 2024, 4:43pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/7 "2024-07-10T16:43:13Z")

</div>

I was thinking it had to be Mutable. But as it turns out, Observables allow you to mutate immutable objects (if that makes sense)

I’m doing something like:

```julia
using Observables, GeometryBasics

struct Particle2D{T<:Real}
    position::Observable{Point{2, T}}
    velocity::Observable{Point{2, T}}
    acceleration::Observable{Point{2, T}}
    mass::T
    charge::T
    shape::Observable
    size::Observable{T}
    alpha::Observable{T}

    function Particle2D(
        position::Point{2, T}=Point2i(0,0),
        velocity::Point{2, T}=Point2i(0,0),
        acceleration::Point{2, T}=Point2i(0,0),
        mass::T=1,
        charge::T=1,
        shape=GeometryBasics.Circle,
        size::T=1,
        alpha::T=1
    ) where {T<:Real}
        new{T}(Observable(position), Observable(velocity), Observable(acceleration), mass, charge, Observable(shape), Observable(size), Observable(alpha))
    end

    function Particle2D(
        position::Point{2, <:Real}=Point2i(0,0),
        velocity::Point{2, <:Real}=Point2i(0,0),
        acceleration::Point{2, <:Real}=Point2i(0,0),
        mass::Real=1,
        charge::Real=1,
        shape=GeometryBasics.Circle,
        size::Real=10,
        alpha::Real=1
    )
        super_T = promote_type(
            eltype(position),
            eltype(velocity),
            eltype(acceleration),
            typeof(mass),
            typeof(charge),
            typeof(size),
            typeof(alpha)
        )

        new{super_T}(
            Observable(convert(Point{2, super_T}, position)),
            Observable(convert(Point{2, super_T}, velocity)),
            Observable(convert(Point{2, super_T}, acceleration)),
            convert(super_T, mass),
            convert(super_T, charge),
            Observable(shape),
            Observable(convert(super_T, size)),
            Observable(convert(super_T, alpha))
        )
    end
end

"""
julia> Particle2D()
Particle2D{Int64}(Observable([0, 0]), Observable([0, 0]), Observable([0, 0]), 1, 1, Observable(Circle), Observable(10), Observable(1))

julia> Particle2D(Point(1,2))
Particle2D{Int64}(Observable([1, 2]), Observable([0, 0]), Observable([0, 0]), 1, 1, Observable(Circle), Observable(10), Observable(1))

julia> @benchmark Particle2D()
BenchmarkTools.Trial: 10000 samples with 168 evaluations.
 Range (min … max): 644.048 ns … 23.988 μs ┊ GC (min … max): 0.00% … 95.21%
 Time (median): 676.786 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 768.488 ns ± 1.027 μs ┊ GC (mean ± σ): 9.29% ± 6.68%

  ▄▇█▆▇▇▅▃▂▁▂▃▂▂▂▂▂▃▂▂▂▁▁▁▂▁▁▁▁ ▂
  █████████████████████████████████▇▆▆▅▆▆▆▄▆▅▅▆▅▄▅▁▅▃▄▃▃▁▃▁▅▅▄ █
  644 ns Histogram: log(frequency) by time 1.1 μs <

 Memory estimate: 1.36 KiB, allocs estimate: 27.

 
---

julia> @benchmark Particle2D().position[] += [1,2]
BenchmarkTools.Trial: 10000 samples with 98 evaluations.
 Range (min … max): 793.878 ns … 61.263 μs ┊ GC (min … max): 0.00% … 97.09%
 Time (median): 905.102 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 1.095 μs ± 2.381 μs ┊ GC (mean ± σ): 12.22% ± 5.54%

  ▆█▆▆▄▇▆▆▆▅▄▄▄▄▃▃▂▁▁ ▁ ▁ ▁ ▂
  █████████████████████▇█▆▆▅▆▆▅▅▄▅▅▆▅▅▅▆▆▆▆▆▇▇█████████▇▇▇▇▅▆▆ █
  794 ns Histogram: log(frequency) by time 1.92 μs <

 Memory estimate: 1.56 KiB, allocs estimate: 32.

"""

```

as for position, velocity, acceleration… i guess I should name them pos, vel, acc to begin with.

I can not redefine since I do need Observables and need to redefine it, but it happens with immutable structs too somehow! Thanks for that!

---

<div class="post-metadata">

**Author:** ![Maddy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maddy/32/210658_2.png) [@Maddy](https://discourse.julialang.org/u/Maddy)\
**Post date:** [July 10, 2024, 4:54pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/8 "2024-07-10T16:54:59Z")

</div>

Pardon me if I misunderstood you, I am still learning.  
I didn’t catch that.

```jldoctest
julia> mutable struct Particle
       position
       pos
       end

julia> Particle(x) = Particle(x, x)
Particle

julia> getproperty(p::Particle, sym) = getfield(p, sym === :pos ? :position : sym)
getproperty (generic function with 1 method)

julia> setproperty!(p::Particle, sym, x) = setfield!(p, sym === :pos ? :position : sym, x)
setproperty! (generic function with 1 method)

julia> p = Particle(1)
Particle(1, 1)

julia> p.position = 2
2

julia> p
Particle(2, 1)

julia> setproperty!(p, :position, 3)
3

julia> p
Particle(3, 1)

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 10, 2024, 6:05pm UTC](https://discourse.julialang.org/t/creating-an-alias-for-a-struct-field/116873/9 "2024-07-10T18:05:03Z")

</div>

The intent was to have one field in `Particle` that can be accessed in two ways:

```julia
julia> mutable struct Particle
              position
              end

julia> getproperty(p::Particle, sym :: Symbol) = getfield(p, sym === :pos ? :position : sym)
getproperty (generic function with 1 method)

julia> setproperty!(p::Particle, sym :: Symbol, x) = setfield!(p, sym === :pos ? :position : sym, x)
setproperty! (generic function with 1 method)

julia> p = Particle(1)
Particle(1)

julia> p.position = 2
2

julia> p
Particle(2)

julia> setproperty!(p, :pos, 3)
3

julia> p
Particle(3)

```
