# Why I can't set what parameters are mutable explicitly?

**URL:** https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091
**Category:** Offtopic
**Tags:** functions
**Created:** [August 21, 2022, 3:50pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091 "2022-08-21T15:50:10Z")
**Posts on this page:** 20
**Page:** 3

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 22, 2022, 10:56am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/42 "2022-08-22T10:56:21Z")

</div>

> [@Dan\_Micsa](#):
>
> even Python tries hard to solve it somehow

Do you have any information about this?

---

<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: [August 22, 2022, 11:23am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/43 "2022-08-22T11:23:30Z")

</div>

Is it just me or has this been worded very confusingly? It’s not that OP wants an argument to be specified as immutable (an instance of an immutable type), rather the argument would be specified as not being mutated in the method. I’m rather baffled that the discussion is about method definitions because I could just look at the method definition and see if the argument is mutated in a few telltale ways:

1. `arg[i] = value` does `setindex!`
2. `arg.afield = value` does `setproperty!`
3. `somefunction!(arg, barg, carg)` uses the `!` convention to indicate that a method does mutation, so I’ll check _that_ method to see if `arg` might be mutated.

I’ve read about a similar request but about function _calls_, and iirc, people figured out that any mark indicating “this argument isn’t mutated” in a function call could only be enforced if the method definition is inspected, which requires the dispatch to be known. So people just decided to write comments or name mutated variables with `!` indicators.

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 11:30am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/44 "2022-08-22T11:30:44Z")

</div>

They have Final that somehow works sometimes. Is not enforced by language or interpreter only with some various degrees of success. I hate this sort of plumbing in languages when Treating such an important problem in a language is so important: The side effects of a call.

I would like to see something like this in Julia:

```julia
function g(a!, b, c!)

```

It will help clarify a call, is in Julia spirit and should work in version 1.x too. But NOT as syntactic sugar enforced by complier!

[https://mypy.readthedocs.io/en/stable/final\_attrs.html](https://mypy.readthedocs.io/en/stable/final_attrs.html)

---

<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: [August 22, 2022, 11:31am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/45 "2022-08-22T11:31:06Z")

</div>

Also, expanding the use of `const` to arguments won’t help. Instances are not `const`, _variables_ are. So all `const` does is prevent the variable from being reassigned. It however does nothing to prevent the instance from being mutated; the instance’s type is either immutable or mutable. `ReadOnlyArray` is an immutable wrapper of a possibly mutable `AbstractArray`, and it forwards to all wrapped array’s methods except the mutating `setindex!`; if you pass a `ReadOnlyArray` into a function call, you can guarantee that no mutation happens, just throwing an error if the function tries.

Here’s an example rewriting the OP’s code into the global scope where `const` does work.

```julia
julia> const v = [1, 2]
2-element Vector{Int64}:
 1
 2

julia> v[2] = 3 # mutation of the instance
3

julia> v # mutation worked
2-element Vector{Int64}:
 1
 3

julia> v = 3 # reassignment of variable failed
ERROR: invalid redefinition of constant v

```

mypy’s Final seems to be analogous to `const`: “_Final names_ are variables or attributes that should not be reassigned after initialization.”

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 11:33am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/46 "2022-08-22T11:33:23Z")

</div>

All arguments should be const by default.

---

<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: [August 22, 2022, 11:38am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/47 "2022-08-22T11:38:30Z")

</div>

Even if they were (and we would need some `nonconst` keyword to allow some variables to be reassigned), it would still not prevent mutation. My example above clearly demonstrates mutation of an instance assigned to a `const` variable.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 22, 2022, 11:47am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/48 "2022-08-22T11:47:13Z")

</div>

> [@Benny](#):
>
> and we would need some `nonconst` keyword to allow some variables to be reassigned

Re-assignment would anyway not be visible outside of the called function, so the usefulness is unclear.

But, you are right: it is _mutability_ which is the issue here, not whether bindings are `const`.

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 11:49am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/49 "2022-08-22T11:49:49Z")

</div>

This would be very good if are enforced by the compiler not optional things.

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 11:54am UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/50 "2022-08-22T11:54:42Z")

</div>

It is very important that a class that has mutable fields or vector to not be changed inside a call by default or no side effects please by default! I would preffer this to be the default behaviour and to use ‘!’ to flag mutable variables. Something like:

```julia
g(a!, b!, c)
swap(a!, b!)

```

not g!(a, b, c) how it is now.

This must be enforced by the compiler.

---

<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: [August 22, 2022, 12:11pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/51 "2022-08-22T12:11:48Z")

</div>

You’re talking about something I remember from that thread. `g(a!, b!, c)` is actually a fairly unusable syntax, and it’s apparent if we look at a definition and a call:

```julia
function g(a!, b!, c)
   # mutates a! and b!, c is not mutated
end

# many lines later, or even in a different file
function f(x, y, z)
  g(x, y, z)
end

```

When we call `g`, we can’t tell if it mutates anything at all. The `!` method convention is only necessary at the _call_, not the definition. We wouldn’t need it at the definition to see if anything is mutated, we could just inspect the method body.

Well okay, let `g` be `g!` then, let’s re-examine your idea:

```julia
function g!(a!, b!, c) # already legal to write, just not enforced
   # mutates a! and b!, c is not mutated
end

# many lines later, or even in a different file
function f(x, y!, z!)
  g!(x, y!, z!) # mutates x and y!, z! is not mutated
end

```

Oh no, just because I didn’t put a `!` in `x`’s name doesn’t mean I can force `g!` to not mutate `a! = x`. The body of `g!` doesn’t even know what the names `x, y!, z!` are, their instances were already assigned to `a!, b!, c` at the header. Variable names are fickle, if we need an instance to never mutate we need an immutable _type_.

> [@Dan\_Micsa](#):
>
> This must be enforced by the compiler.

This does happen. The compiler notices that an immutable type does not implement a mutating method, so it makes code that throws a `MethodError`. Thing is, compilation of a method only happens upon a function call that dispatches to it, and I think that is far too late for your liking.

---

<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: [August 22, 2022, 12:24pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/52 "2022-08-22T12:24:05Z")

</div>

> [@Dan\_Micsa](#):
>
> It is very important that a class that has mutable fields or vector to not be changed inside a call by default or no side effects please by default!

Note that in Julia this kind of guarantee is particularly hard, because a user can overload an inner method that is called by a “non-mutating” function, making it mutating. I think you would have to combine that with giving up on generics at the same time:

```julia
julia> add_one(x) = x + 1
       function nomutationhere(x)
           return add_one(x)
       end
nomutationhere (generic function with 1 method)

julia> struct A
           x::Vector{Int}
       end

julia> a = A([0,0])
A([0, 0])

julia> add_one(a::A) = a.x[1] += 1
add_one (generic function with 2 methods)

julia> nomutationhere(a)
1

julia> a
A([1, 0])

```

I mean, when someone writes the `nonmutationhere` function, should he/she assume that nobody will never come up with a use for that function for a different type of object for which that function does mutate the object?

This kind of flexibility and composability clearly has its tradeoffs, but it does not seem clear to me if there is anything that could improve on this. I myself have some packages where I define `const foo = foo!`, for instance because the `foo` is mutating or not depending on the type of variable the user wants to use, and the alternative would be to have almost identical functions for each situation (and having both names allows the user to stick to the convention of mutability).

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 12:26pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/53 "2022-08-22T12:26:24Z")

</div>

I don’t much understand what you want to say. A call to a functions needs to enforce declaration of the side effect. How it is used is irrelevant.

Let’s take a simple example:

```julia
#using v1.8
f1(x)= x[1] = 2
f2!(x)= x[1] = 3
f3!(x!)= x[1] = 4
f4(x!)= x[1] = 5

v = [1]
f1(v) #wow, silently alter my vector!
f2!(v)
f3!(v) #error
f4(v) #error

```

I don’t find this behaviour too good.

---

<div class="post-metadata">

### Author: ![benninkrs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benninkrs/32/3191_2.png) [@benninkrs](https://discourse.julialang.org/u/benninkrs)
#### Post date: [August 22, 2022, 12:26pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/54 "2022-08-22T12:26:25Z")

</div>

> [@Benny](#):
>
> If we need an instance to never mutate we need an immutable _type_.

The OP is not looking for an instance that never mutates. He wants a mutable instance with the assurance that a called function will not mutate it.

---

<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: [August 22, 2022, 12:53pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/55 "2022-08-22T12:53:04Z")

</div>

For flat arrays this is exactly the `f(ReadOnlyArray(a))` solution proposed above.  
Maybe, something more general for arbitrarily nested mutable structs, would also be useful…

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 12:55pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/56 "2022-08-22T12:55:40Z")

</div>

Is not only for flat arrays is for any aother type that passes by ref.

---

<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: [August 22, 2022, 1:02pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/57 "2022-08-22T13:02:53Z")

</div>

Yes, I’ve noted that as well when I first commented. However, I believe that to be infeasible. `A[i] = value` and `A.y = value` are both syntactic sugar for method calls, specifically `setindex!` and `setproperty!`. If we somehow mark the variable `A` to not be mutated in a method, the compiler has to figure out whether methods like `f!(A, B, C)` and `h!(a, A)` mutate `A`’s possibly mutable instance and throw an error if any do. Hypothetically possible but it would take a lot of work (compilation takes longer) and there’s just no system even resembling that in Julia.

OP used a C++ example `void g(int a, int& b, int& c)` and someone else said it is analogous to `g(a::Int, b::Ref{Int}, c::Ref{Int})`. Well, not exactly, C++ and Julia treat variables and arguments very differently, so even that example is making an imperfect analogy between Julia’s _instances_ and the C++ variables. In Julia, `a = 0` has an immutable `Int` instance, so the only way `a`’s value can change is reassigning a different instance e.g. `a = 2` or `a += 1`. In C++, you can change `int a`’s value without reassigning it at all:

```julia
#include <iostream>

void g(int& a2) {
    a2 += 1;
}

int main()
{
    int a = 0;
    std::cout<<a;
    g(a); //not reassigning a
    std::cout<<a;
    return 0;
}

// Equivalent in Julia requires a = Ref(0)

```

C++ is just one of those languages where a variable and its value are more…tied together. In languages like Julia and Python, variables are just nametags you slap onto an instance, and you can put on or take off as many nametags as you want. The closest analog of `const` C++ variables in Julia _is_ instantiating immutable types. Any `mutable struct` type can have a `struct` version; `Array`s aren’t `mutable struct`s but `ReadOnlyArrays` is the `struct` version. The `const` in Julia (and the Final in mypy) is just not at all relevant, despite sharing a name.

---

<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: [August 22, 2022, 1:22pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/58 "2022-08-22T13:22:03Z")

</div>

> [@Dan\_Micsa](#):
>
> ```julia
> ...
> f3!(x!)= x[1] = 4
> f4(x!)= x[1] = 5
> ...
> f3!(v) #error
> f4(v) #error
> 
> ```

Those errors are because you forgot to rename `x` in the method body to match the argument `x!`. That’s why all the errors say “UndefVarError: x not defined”.

Also, by your proposal, shouldn’t all the mutated `x` be named `x!` instead, e.g. `x![1] = 2`? That way, you could accomplish what you want to a limited degree with “UndefVarError: x! not defined”.

---

<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: [August 22, 2022, 1:28pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/59 "2022-08-22T13:28:26Z")

</div>

Enforcing immutability would be useful even without static analysis - most Julia errors are runtime anyway. But this is very challenging to make work in the general case.  
For example, this should error:

```julia
function f(x)
     a = first(x).a
     ...
     g(a[2])
     ...
end

function g(b)
    empty!(b[2])
end

f(Immutable(x))

```

---

<div class="post-metadata">

### Author: ![Dan\_Micsa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan_micsa/32/30233_2.png) [@Dan\_Micsa](https://discourse.julialang.org/u/Dan_Micsa)
#### Post date: [August 22, 2022, 1:54pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/60 "2022-08-22T13:54:55Z")

</div>

Still doesn’t work normal.  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/5/f5ebcdf6b61ddf1a2c1afe01b9de89a738f2a27e.png)

---

<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: [August 22, 2022, 1:56pm UTC](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091/61 "2022-08-22T13:56:45Z")

</div>

Well, you didn’t assign a global variable `v!`…as the error tells you.

[Previous page](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091.md?page=2)

[Next page](https://discourse.julialang.org/t/why-i-cant-set-what-parameters-are-mutable-explicitly/86091.md?page=4)
