# Calling a function to change a struct?

**URL:** <https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846>\
**Category:** General Usage\
**Created:** [May 14, 2023, 7:20pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846 "2023-05-14T19:20:45Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![hshackle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hshackle/32/47114_2.png) [@hshackle](https://discourse.julialang.org/u/hshackle)\
**Post date:** [May 14, 2023, 7:20pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/1 "2023-05-14T19:20:45Z")

</div>

I am trying to use a function in order to modify a struct that is passed to it as a variable. Below is a minimal bit of code I have put together to illustrate my confusion.

```julia
struct a
    x::Int
    y::Int
end

function switchVariables!(b::a)
    newB = a(b.y, b.x)
    b = newB
    println(b)
end

b = a(1, 2)
println(b)
switchVariables!(b)
println(b)

```

The two `println` calls outside of the `switchVariables!` function return `a(1, 2)`, whereas the one inside the function returns `a(2, 1)`. So it looks like the proper operation is being done to `b` inside the function, but not outside of it. I’ve poked around with variants like `b = deepcopy(newB)` but have not had any luck. Would someone be able to explain to me what is going on here? I recognize that for this minimal example, it would probably be better to just return the desired modified struct rather than explicitly trying to modify `b` - while the same might be true for the actual code that I’m working on, I would at least like to understand why the above code doesn’t work the way I would naively expect it to. Thanks!

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 14, 2023, 7:36pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/2 "2023-05-14T19:36:43Z")

</div>

You must pass a reference to your struct to your fuction.

Type

```julia
?Ref

```

at the Julia prompt.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 14, 2023, 7:38pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/3 "2023-05-14T19:38:19Z")

</div>

1. The struct created is immutable, you cannot modify it.

2. Doing `b = new struct`, inside the function, is just assigning the label `b` to a new struct.

3. That label is local to the scope of the function.

You need to use `b = switch(b)` to assign the label `b` of the outer scope to the new struct created in the function. But that is not mutating anything. Usually that’s fine and the way to go, but you can also use a _mutable_ struct and get actually the behavior you were expecting.

Ps. Think of an immutable struct as a number. You are doing:

```julia
function switch(b)
    newb = 2
    b = newb
    return b
end

b = 1
switch(b)

```

You will see that `b` does not change outside `switch`, because the label `b` of the outer scope was bound to the value `1` and that was not changed in that scope. You need to do here `b = swich(b)`. The same goes for immutable objects, like your struct. In any case, you are not modifying the immutable **number 1** , which is an immutable value, corresponding to your struct.

---

<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:** [May 14, 2023, 7:52pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/4 "2023-05-14T19:52:59Z")

</div>

To get the behaviour you ask for, you should do this:

```julia
mutable struct a
    x::Int
    y::Int
end

function switchVariables!(b::a)
   b.x, b.y = b.y, b.x
end

```

Unless you declare the struct as `mutable` it will be immutable, i.e. the content can’t be modified. This has a number of advantages for performance. But if you want modifiable struct you must explicitly use the `mutable` keyword. The way you wrote your function would have worked if arguments were “called by name”, Julia does not support that.

---

<div class="post-metadata">

**Author:** ![dylanxyz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dylanxyz/32/36646_2.png) [@dylanxyz](https://discourse.julialang.org/u/dylanxyz)\
**Post date:** [May 14, 2023, 8:03pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/5 "2023-05-14T20:03:08Z")

</div>

```julia
global b = newB

```

---

<div class="post-metadata">

**Author:** ![MilkshakeForReal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milkshakeforreal/32/32861_2.png) [@MilkshakeForReal](https://discourse.julialang.org/u/MilkshakeForReal)\
**Post date:** [May 14, 2023, 8:13pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/6 "2023-05-14T20:13:37Z")

</div>

Try [JuliaObjects/Accessors.jl: Update immutable data (github.com)](https://github.com/JuliaObjects/Accessors.jl)

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 14, 2023, 9:12pm UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/7 "2023-05-14T21:12:42Z")

</div>

If you can get `@set` to turn iteration-based destructuring assignment `b.x, b.y = b.y, b.x` to instantiation `a(b.y, b.x)` then please provide the code because AFAIK Accessors.jl can’t do that yet. It’s not possible to do the changes separately because both the previous x and y fields must be retrieved before replacing either.

```julia
julia> @set b.x = b.y
a(2, 2)

julia> @set b.x, b.y = b.y, b.x
(2, 1)

```

EDIT: Answered my own question, but tbf, it is a longstanding missing feature in Accessors.jl and the predecessor Setfield.jl. `setproperties` is only mentioned in the docs under an explicitly experimental `mapproperties`, so it could easily be gone in minor revisions. I don’t know the internal workings of why `@set` can’t just do what `setproperties` can.

```julia
julia> b
a(1, 2)

julia> setproperties(b, (x = b.y, y = b.x))
a(2, 1)

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 15, 2023, 12:13am UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/8 "2023-05-15T00:13:34Z")

</div>

Note also that Accessors, or Setfield, do not mutate immutable data, really, they are just convenience macros to redefine new immutable structs. The issue the OP has would be the same with it:

```julia

julia> using Accessors

julia> struct A
           i
           j
       end

julia> function set_i(a)
           a = @set a.i = 0
           return a
       end
set_i (generic function with 1 method)

julia> b = A(1,1)
A(1, 1)

julia> set_i(b)
A(0, 1)

julia> b # doesn´t change
A(1, 1)

```

---

<div class="post-metadata">

**Author:** ![MilkshakeForReal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milkshakeforreal/32/32861_2.png) [@MilkshakeForReal](https://discourse.julialang.org/u/MilkshakeForReal)\
**Post date:** [May 18, 2023, 4:49am UTC](https://discourse.julialang.org/t/calling-a-function-to-change-a-struct/98846/9 "2023-05-18T04:49:00Z")

</div>

Yeah you’re absolutely right!
