All types in Q# are value types. Q# does not have a concept of a reference or pointer. Instead, it allows you to reassign a new value to a previously declared variable via a
set statement. For example, there is no distinction in behavior between reassignments for variables of type
Int or variables of type
Int. Consider the following sequence of statements:
mutable arr1 = new Int;
let arr2 = arr1;
set arr1 w/= 0 <- 3;
The first statement instantiates a new array of integers
[0,0,0] and assigns it to
The next statement assigns that value to a variable with name
arr2. The last statement creates a new array instance based on
arr1 with the same values except for the value at index 0 which is set to 3. The newly created array is then assigned to the variable
arr1. The last line makes use of the abbreviated syntax for evaluate-and-reassign statements, and could equivalently have been written as
set arr1 = arr1 w/ 0 <- 1;.
After running the three statements,
arr1 will contain the value
arr2 remains unchanged and contains the value
Q# clearly thus distinguishes the mutability of a handle and the behavior of a type. Mutability within Q# is a concept that applies to a symbol rather than a type or value; it applies to the handle that allows you to access a value rather than to the value itself. It is not represented in the type system, implicitly or explicitly.
Of course, this is merely a description of the formally defined behavior; under the hood, the actual implementation uses a reference counting scheme to avoid copying memory as much as possible. The modification is specifically done in place as long as there is only one currently valid handle that accesses a certain value.