# An Issue in Defining a Mutating Function

This might sound a stupid question to experienced Julia users. When I define a simple mutating function as:

``````function foo!(x)
x = x + 1
end
``````

I expect the function to change the value of its argument. However when I execute the following:

``````x = 3
foo!(x)
x
``````

the value of x is still 3. What’s going on here?

two things.

1. `Int`s are immutable objects, so you can’t mutate them in any way
2. Even if `x` was mutable (like an array), your method would not mutate it. All you are doing is assigning a new binding inside the function. The outer scope doesn’t know about that.

You might want to use a vector here.

``````function foo!(x)
x = x + 1
end

x = 
foo!(x)
``````
3 Likes

`Ref` is also a good option (and has slightly better performance):

``````julia> foo!(x) = x[] += 1
foo! (generic function with 1 method)

julia> x = Ref(3)
Base.RefValue{Int64}(3)

julia> foo!(x)
4

julia> x
Base.RefValue{Int64}(4)
``````
2 Likes

If you want to mutate a global variable in a function, you should declare it to be `global`, or else all variables in your function will be treated as local variables. This works for your example:

``````julia> function foo!(x)
global x += 1
end
foo! (generic function with 1 method)

julia> x = 3
3

julia> foo!(x)
4

julia> x
4
``````

Note that this violates the expectation of `!` to mean that the function will mutate its argument:

``````julia> function foo!(x)
global x += 1
end
foo! (generic function with 1 method)

julia> x = 3
foo!(x)
4

julia> y = 10
foo!(y)
5

julia> y
10
``````
1 Like

So would

``````julia> x::Int64 = 1
1

julia> function foo()
global x += 1
end
foo (generic function with 1 method)

julia> foo()
2

julia> foo()
3

julia> x
3
``````

be a more standard way to do this?

This is not mutation either. That’s equivalent to

``````x = 1
x = 2
``````

Which is not mutating, is assigning the label `x` to a new value.

Mutability is a property of the value, not of the label. And an Int is not mutable.

Concerning the original question, probably what the OP wants is

``````x = 1
f(x) = x + 1
# call reassigning x to the return value
x = f(x)
``````

(Although technically correct, I don’t think suggesting to use arrays or refs is actually what will solve the problem, and may lead to very bad initial programming habits and experience with Julia; this may help: Assignment and mutation · JuliaNotes.jl).

3 Likes