# How to represent struct component

**URL:** <https://discourse.julialang.org/t/how-to-represent-struct-component/97770>\
**Category:** General Usage\
**Tags:** struct\
**Created:** [April 22, 2023, 2:35am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770 "2023-04-22T02:35:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![David\_Sagan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david_sagan/32/33792_2.png) [@David\_Sagan](https://discourse.julialang.org/u/David_Sagan)\
**Post date:** [April 22, 2023, 2:35am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/1 "2023-04-22T02:35:38Z")

</div>

I want to be able to define a variable that represents a component of a structure and then use this variable to set or get the structure component. One thought I have is to do something like:

```julia
julia> mutable struct A
       a1; a2
       end

julia> a=A((1,2),3)

julia> var = :a2
:a2

julia> getproperty(a, var)
3

```

So far so good. But if I try to do the same thing for an array component I have a problem:

```julia
julia> var = :(a1[1])
:(a1[1])

julia> getproperty(a, var)
ERROR: MethodError: no method matching getproperty(::A, ::Expr)
Closest candidates are:
  getproperty(::Any, ::Symbol) at Base.jl:38
  getproperty(::Any, ::Symbol, ::Symbol) at Base.jl:50
Stacktrace:
 [1] top-level scope
   @ REPL[14]:1

```

My question is what is the simplest way to do what I want? Any solution would also have to work with nested structures.

---

<div class="post-metadata">

**Author:** ![OmarElrefaei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/omarelrefaei/32/43002_2.png) [@OmarElrefaei](https://discourse.julialang.org/u/OmarElrefaei)\
**Post date:** [April 22, 2023, 3:43am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/2 "2023-04-22T03:43:54Z")

</div>

I’m not sure if I can help with your need, but I can just point out that the source of the error is that `:(a1[1])` is a different syntactic construct altogether:

```julia
julia> :a |> typeof
Symbol

julia> :(a) |> typeof
Symbol

julia> :(a[1]) |> typeof
Expr

```

Here is some potentially relevant docs, but fwiw it feels like what you’re trying to do is a bit unconventional, maybe if you expand of _why_ you want to do it someone could point out the conventional way if doing it.  
[https://docs.julialang.org/en/v1/manual/metaprogramming/](https://docs.julialang.org/en/v1/manual/metaprogramming/)  
[https://docs.julialang.org/en/v1/base/base/#Core.Symbol](https://docs.julialang.org/en/v1/base/base/#Core.Symbol)  
[https://docs.julialang.org/en/v1/base/base/#Core.Expr](https://docs.julialang.org/en/v1/base/base/#Core.Expr)

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [April 22, 2023, 3:52am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/3 "2023-04-22T03:52:22Z")

</div>

The most obvious approach would be to turn your expression into a lambda function. This may require some metaprogramming.

```julia
julia> mutable struct A
           a1; a2
       end

julia> x = A([1,2,3],[4,5,6])
A([1, 2, 3], [4, 5, 6])

julia> var = A->A.a2[2]
#3 (generic function with 1 method)

julia> x |> var
5

```

[https://docs.julialang.org/en/v1/manual/metaprogramming/](https://docs.julialang.org/en/v1/manual/metaprogramming/)

---

<div class="post-metadata">

**Author:** ![David\_Sagan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david_sagan/32/33792_2.png) [@David\_Sagan](https://discourse.julialang.org/u/David_Sagan)\
**Post date:** [April 22, 2023, 4:13am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/4 "2023-04-22T04:13:17Z")

</div>

Yes this is exactly what I wanted! Much Thanks.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 22, 2023, 6:46pm UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/5 "2023-04-22T18:46:15Z")

</div>

> [@David\_Sagan](#):
>
> define a variable that represents a component of a structure and then use this variable to set or get the structure component.

That’s exactly what lenses are!

```julia
using Accessors

var = @optic _.a2 # variable that represents a component of a structure 
var(a) # get the component
new_a = set(a, var, 123) # return object like a, but with new_a.a2 set to 123

```

Array components, and basically anything else is supported with the same syntax, including arbitrary combinations: try `@optic _[1]`, `@optic first(_.a2)` etc.

---

<div class="post-metadata">

**Author:** ![David\_Sagan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david_sagan/32/33792_2.png) [@David\_Sagan](https://discourse.julialang.org/u/David_Sagan)\
**Post date:** [April 22, 2023, 9:34pm UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/6 "2023-04-22T21:34:58Z")

</div>

@aplavin This is cool. But I don’t see how to set a value without making a copy. Setting without copying is needed for my application.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 22, 2023, 11:20pm UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/7 "2023-04-22T23:20:28Z")

</div>

Out of the box, `Accessors` only directly support immutable modifications. You can still use these lenses as “variables that represents a component of a structure”, but implement mutations yourself.

But first, are you sure you need actual mutability here? Often, it’s more efficient to use immutable structs and create new instances with modified values, as `Accessors` do.

---

<div class="post-metadata">

**Author:** ![David\_Sagan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david_sagan/32/33792_2.png) [@David\_Sagan](https://discourse.julialang.org/u/David_Sagan)\
**Post date:** [April 23, 2023, 1:34am UTC](https://discourse.julialang.org/t/how-to-represent-struct-component/97770/8 "2023-04-23T01:34:41Z")

</div>

Yes this is needed since there will be multiple variables that will point to the same memory. So, in my original example, if the set `b = a` is done after `a` is defined, `b` should change if `a` changes.
