Storing elements in a sequence (Part 2)

Mutation

The variable "pets" points to the sequence "cat", "ape", "dogs", "fox", "bat" with indices 0, 1, 2, 3, 4, respectively.

Here's what mutation looks like. When we assign a new value to one of the positions, the address associated with that index in changed. That is, the sequence itself is being changed.

For example, as illustrated in the figure, the pseudocode pets[4] ← "ant" changes the address stored within the sequence. This results in the sequence being changed.


Dangers of mutation

As you can imagine, mutation is quite handy. As you can also imagine, mutation is somewhat dangerous. This isn't the only time we'll see this combination of traits.

Definition

Aliasing occurs when two different names are used for the same data.

One of the dangers of mutation is aliasing, that is, mutable data having two different names. This is to be avoided when possible.

Caution

Avoid aliasing where possible.

Example with immutable data

Going back to our earlier example, we will see that it is not dangerous to assign two names to immutable data. Consider the sequence of pseudocode given below executed in the order listed.

  1. Variable x stores the value 10.
    x ← 10:
    We first assign the value 10 to the variable x.
  2. Variable x is reassigned the value 20.
    x ← 20:
    As before, we reassign x to 20.
  3. A new variable y is pointed to the same address location that contains the value 20. Now both variables x and y point to the same memeory address location.
    y ← x:
    Then we let y use the same address.
  4. Variable x is now assigned the value 30. The variable y is kept unchanged: it points to the address that contain the value 20.
    x ← 30:
    What happens when x changes? The address associated with x changes to point to a new value, and y stays the same. The key point here is that changes to x do not make change to y. Not so with aliasing.

Aliasing

The variable "pets" points to the sequence "cat", "ape", "dogs", "fox", "bat" with indices 0, 1, 2, 3, 4, respectively.

As shown in the figure, we have a sequence with the name pets. The sequence consists of the values "cat", "ape", "dog", "fox", "bat" with indices 0, 1, 2, 3, 4, respectively.


The address to which the variable pet points is now assigned to the variable names as well.

As shown in the figure, now we assign the same address to the variable names: names ← pets.


The valued stored in position 4 of the variable names is changed to "ant". This causes the sequence associated with the variable pets to change so that the index 4 now points to the address with stored value "ant".

Now let's change the value stored in position 4 of names: names[4] ← "ant". What happened to pets? It was changed too!


Aliasing is confusing, so we try to avoid it. But sometimes it is unavoidable, as we'll see.

Using sequences as inputs to functions

What happens when we call a function on mutable data, like a sequence? There are two ways that functions can handle input parameters: call by value and call by reference. In call by value, it is a copy of the input data that is changed inside the function call. In other words, the function uses a copy of the input data. For example, in the following pseudocode, no changes to input variable, total , occur:

total ← 20 many ← paint(total)

Here, when we call the function paint on the parameter total, the value assigned to total does not change.

In contrast, when a function that uses call by reference, the function call uses the reference to the parameter, that is, it uses the address to access the original data. In other words, the function uses the input value itself. This results in changing the input as a side effect. This can be very useful as long as you are aware what is happening! Make sure to inform yourself.

Caution

Make sure you know how each function behaves.

Built-in functions

Ways to create sequences:
  • Specify the entire sequence of elements.
  • Create an empty sequence and then add elements.
  • Copy an existing sequence and modify it.

What types of built-in functions are there? We need ways to create sequences, such as by specifying all the elements, or, since mutation is possible, by creating an empty sequence and then changing it by adding elements. Yet another way to create a sequence is to copy a sequence and then possibly make changes to the copy.

Language-dependent:
  • Elements can be of different types.
  • Elements can only be added in certain positions.
  • Elements can be deleted.

Depending on the programming language, a sequence can consists of different types of elements, such as both strings and numbers. Sometimes elements can only be added at certain positions such as, for example, only at the beginning or at the end. Again, depending on the language, elements can be deleted to shorten a sequence. Whatever functions a language provides, make sure you know whether the input will be altered or not.

Caution

Make sure you know if the function creates a new sequence or alters the input.