# Mutating function parameters

**URL:** <https://discourse.julialang.org/t/mutating-function-parameters/108268>\
**Category:** New to Julia\
**Created:** [January 2, 2024, 5:13pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268 "2024-01-02T17:13:03Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [January 2, 2024, 5:13pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/1 "2024-01-02T17:13:03Z")

</div>

```julia
using DataFrames

function doit!(flag, df)
    if flag==true
        flag=false
    end
    if df[1, :flag]==true
        df[1, :flag]=false
    end
    println("Within doit, flag=",flag,", df=",df[1, :flag])
end

function main()
    df = DataFrame(flag = [true])
    flag=true
    for i = 1:2
        println("$i - Before, flag=", flag, ", df=", df[1, :flag])
        doit!(flag, df)
        println("$i - After, flag=", flag, ", df=", df[1, :flag])
    end
end

main()

```

Generates the output

```julia
1 - Before, flag=true, df=true
Within doit, flag=false, df=false
1 - After, flag=true, df=false
2 - Before, flag=true, df=false
Within doit, flag=false, df=false
2 - After, flag=true, df=false

```

And the [docs](https://docs.julialang.org/en/v1/manual/functions/) make clear that this is the expected behaviour. It says about passing by sharing that “modifications to mutable values (such as `Array` s) made within a function will be visible to the caller.” It also gives an example of how asigining a new value to a simple (numeric) parameter “changes the _binding_ (“name”) to refer to a new value”.

So, two questions:

- Why don’t simple variables mutate like arrays? What other types have this non-mutating behaviour.
- Can I cause simple parameters to mutate in the same way as arrays or is this not possible. (I realise I could simply return the changed value).

Thanks,

Tim

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [January 2, 2024, 5:31pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/2 "2024-01-02T17:31:33Z")

</div>

Julia’s “variables” are about naming and that’s it. I really wish that we wouldn’t use the word “variable” because that — to me — implies some sort of mutable state. And I wish we’d use a “naming” operator that looks more distinct from mutating operations. But this is the world we live in:

- `flag = true` is you deciding that you want to use the name `flag` to identify `true` (or whatever you put on the right hand side). You can re-use names as much as you want, but new names you (re-)define only affect your current scope by default. This is even the case for the `op=` shorthands — `x += 1` is you saying that you have a better use for the name `x`, and it’s going to be whatever `x` was `+ 1`.

- Indexed assignments like `df[1, :flag]=false` — despite looking similar to that first bullet’s syntax — don’t have anything to do with naming! They **update** (mutate) the object that `df` names at the passed indices/columns to contain some value.

- Property assignments (like `x.property = blah`) and broadcasted assignment (like `x .= blah`) are similar: they update (mutate) the object that `x` names.

So this has nothing to do with the type — it’s about the syntax you use!

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [January 2, 2024, 5:41pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/3 "2024-01-02T17:41:34Z")

</div>

> [@TimG](#):
>
> Can I cause simple parameters to mutate in the same way as arrays or is this not possible. (I realise I could simply return the changed value).

Take a look at the `Ref` type ([C Interface · The Julia Language](https://docs.julialang.org/en/v1/base/c/#Core.Ref) these docs appear a bit cryptic on first read, a better mental model is given by [What is Ref? - #14 by Oscar\_Smith](https://discourse.julialang.org/t/what-is-ref/47610/14)). You can use it like

```julia
using DataFrames

function doit!(flag::Ref, df)
    if flag[]==true
        flag[]=false
    end
    if df[1, :flag]==true
        df[1, :flag]=false
    end
    println("Within doit, flag=",flag[],", df=",df[1, :flag])
end

function main()
    df = DataFrame(flag = [true])
    flag[]=true
    for i = 1:2
        println("$i - Before, flag=", flag[], ", df=", df[1, :flag])
        doit!(flag, df)
        println("$i - After, flag=", flag[], ", df=", df[1, :flag])
    end
end

main()

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 2, 2024, 6:03pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/4 "2024-01-02T18:03:38Z")

</div>

> [@mbauman](#):
>
> Julia’s “variables” are about naming and that’s it.

(See also the [Assignment vs. Mutation](https://docs.julialang.org/en/v1/manual/variables/#man-assignment-expressions) section of the manual.)

> [@fatteneder](#):
>
> > [@TimG](#):
> >
> > Can I cause simple parameters to mutate in the same way as arrays or is this not possible. (I realise I could simply return the changed value).
> 
> Take a look at the `Ref` type

While you can use `Ref` for this, it’s more idiomatic to simply use the function result to `return` any non-mutable value that you want the caller to see.

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [January 2, 2024, 6:07pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/5 "2024-01-02T18:07:33Z")

</div>

Thank you for this.  
It is very like defining flag as a one element array and mutating that. Is Ref a lighter weight mechanism than this?

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [January 2, 2024, 6:09pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/6 "2024-01-02T18:09:03Z")

</div>

> [@mbauman](#):
>
> Property assignments (like `x.property = blah`) and broadcasted assignment (like `x .= blah`) are similar: they update (mutate) the object that `x` names.

So I could use `flag .= false` to achieve what I want?

[Edit: Answer: no! This generates an error.]

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [January 2, 2024, 6:17pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/7 "2024-01-02T18:17:47Z")

</div>

> [@stevengj](#):
>
> (See also the [Assignment vs. Mutation](https://docs.julialang.org/en/v1/manual/variables/#man-assignment-expressions) section of the manual.)

Thank you.  
I had read this at least once before. However, it doesn’t seem to matter how many times I read the docs, I only learn their content when I trip over something they explain. 🙄

---

<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:** [January 2, 2024, 6:18pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/8 "2024-01-02T18:18:45Z")

</div>

> [@TimG](#):
>
> Why don’t simple variables mutate like arrays? What other types have this non-mutating behaviour.

I think the “why” here is the complicated part. To start, just note that other languages (like Python) behave the same. Others, like Fortran, “mutate” these “simple values” (probably the exception), while others require specific syntax for allowing mutation or not (meaning, copying the value upon passing, or passing the memory reference).

My understanding is that the “why” is a performance optimization, basically. When a “simple value” (put more precisely, the “immutable values”) is passed around, if _the value_ is passed, then all the functions and operations can work on those values without having to care about external effects. Once the function receives the value, it owns it. If the memory address was passed instead, then every function would have to constantly fetch the value from the address to operate. That would be very expensive, and prohibitive when operating on simple things, like numbers. Many performance optimizations that compilers do depend on the guarantee that a value does not change within a subset of operations.

Then why don’t do that with everything? That would be actually very good. Every function would be “pure”, meaning that they would not modify any input value, compiler and programmer lives would be much easier.

The problem is that the “values” can be very large in memory, like is the case of large arrays, and then passing the value around can be too expensive. In that case, “the value” is the address of the array in the memory, but the actual content of the array is not passed around, just fetched or mutated directly in the memory.

So, basically, _do not fight_ against this behavior. Simple “immutable values” should be returned from the functions and reassigned if necessary. That’s how the compiler is expecting you to code, and that’s what will give you the most clear and efficient behavior.

> [@TimG](#):
>
> I only learn their content when I trip over something they explain.

That is what happens to everyone. I think the manual is rather clear now, but sometime ago I compiled some answers about that behavior here, which might help: [Assignment and mutation · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/assignment/)

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [January 2, 2024, 7:48pm UTC](https://discourse.julialang.org/t/mutating-function-parameters/108268/9 "2024-01-02T19:48:12Z")

</div>

That’s really helpful and clear. Thank you.
