What is argument mutability in Mojo?

Mojo is a new programming language, a superset of Python, and is intended for artificial intelligence programming. It uses the newly introduced features to optimize its code to run on custom hardware and also provides low level access to MLIR. This enables the user to create custom data types and abstractions for their hardware allowing them utilize their hardware to the full potential.

Argument mutability

When a variable from one function is passed into another, its scope changes. When this happens, there are some restrictions that the function receiving the variable, must have in terms of the variable's modification. This is referred to as argument mutability whether functions and operations outside a variable's scope are allowed to modify its value or not. Most programming languages do not offer security measures for argument mutability. This can result in some serious memory management issues if some things are overlooked.

Some programming languages have ways to deal with this situation by using an "ownership/borrowing" system. For example, Rust is known for its secure memory management which implements this exact system. Let's have a look at how we roll in Mojo.

Memory ownership

When an argument is passed to a function in Mojo, the compiler follows different semantics based on the keyword used to pass the argument. We have three options for argument ownership:

  • The calleeThe function that is called by another function. function can borrow the argument for temporary use.

  • The callee function can get temporary access to the argument and alter it's value.

  • The callee function can get transferred the ownership of the argument.

The borrowed keyword

A borrowed argument is an immutable reference of the actual argument being passed to the callee function. This means that the function is only able to read and use the value of the argument but not actually alter it.

fn ChangeValue(borrowed a: Int):
a += 1
fn main():
var a: Int = 1
ChangeValue(a)
print (a)

When we try to execute the code above, we get an error that the function cannot alter the argument's value because it is immutable.

The inout keyword

If we want a certain function to modify an argument's value then it should be passed using the inout keyword. This is demonstrated below using the same example as above:

fn ChangeValue(inout a: Int):
a += 1
fn main():
var a: Int = 1
ChangeValue(a)
print (a)

As we can see, the ChangeValue function didn't have any problems updating the argument's value.

Note: When we use the inout keyword, any changes made to the argument inside the function are also reflected outside the function.

The owned keyword

This keyword is used to transfer ownership of a variable to the callee function. The variable is no longer owned by the caller function to lend to other functions. We can use the following example to demonstrate the use of this keyword:

fn take_var(owned x: Int):
print("take ownership")
print(x)
fn use_var(borrowed x: Int):
print("use variable")
print(x)
fn main():
let x: Int = 2
use_var(x)
take_var(x^)
# uncomment to see error
# use_var(x)

As seen in the code above, when we want to transfer the ownership of a variable to another function, we use the ^ post the name of the variable when passing it to the function. After the ownership of the variable is passed to the callee function, it can no longer be used in the caller function and an error will be thrown.

Conclusion

In this Answer, we saw how we can pass arguments with different permissions to other functions. We also saw how we can pass the ownership of the arguments being passed to the callee function. These features give Mojo the security it needs to prevent memory leaks and use a proper memory management infrastructure.

Unlock your potential: Mojo fundamentals series, all in one place!

To deepen your understanding of Mojo, explore our series of Answers below:

Free Resources

HowDev By Educative. Copyright ©2025 Educative, Inc. All rights reserved