An assignment is an expression that stores a new value into a
variable. For example, the following expression assigns the value 1 to
the variable z
:
z = 1
After this expression is executed, the variable z
has the value 1.
Whatever old value z
had before the assignment is forgotten.
The ‘=’ sign is called an assignment operator.
Assignments can store string values also. For example, the following
expression would store the value "this food is good"
in the
variable message
:
thing = "food" predicate = "good" message = [ "this " , thing , " is " , predicate ] ⇒ "this food is good"
(This also illustrates concatenation of strings.)
Most operators (addition, concatenation, and so on) have no effect except to compute a value. If you ignore the value, you might as well not use the operator. An assignment operator is different. It does produce a value, but even if you ignore the value, the assignment still makes itself felt through the alteration of the variable. We call this a side effect.
The left-hand operand of an assignment need not be a variable (see Variables). It can also be an element of a matrix (see Index Expressions) or a list of return values (see Calling Functions). These are all called lvalues, which means they can appear on the left-hand side of an assignment operator. The right-hand operand may be any expression. It produces the new value which the assignment stores in the specified variable, matrix element, or list of return values.
It is important to note that variables do not have permanent types.
The type of a variable is simply the type of whatever value it happens
to hold at the moment. In the following program fragment, the variable
foo
has a numeric value at first, and a string value later on:
>> foo = 1 foo = 1 >> foo = "bar" foo = bar
When the second assignment gives foo
a string value, the fact that
it previously had a numeric value is forgotten.
Assignment of a scalar to an indexed matrix sets all of the elements
that are referenced by the indices to the scalar value. For example, if
a
is a matrix with at least two columns,
a(:, 2) = 5
sets all the elements in the second column of a
to 5.
When an assignment sets the value of a vector, matrix, or array element at a position or dimension outside of that variable’s current size, the array size will be increased to accommodate the new values:
>> a = [1, 2, 3] a = 1 2 3 >> a(4) = 4 a = 1 2 3 4 >> a(2, :) = [5, 6, 7, 8] a = 1 2 3 4 5 6 7 8
Attempting to increase the size of an array such that the desired output size is ambiguous will result in an error:
>> a(9) = 10 -| error: Invalid resizing operation or ambiguous assignment to an out-of-bounds array element
This is because adding the 9th element creates an ambiguity in the desired array position for the value 10, each possibility requiring a different array size expansion to accommodate the assignment.
Assignments may be made with fewer specified elements than would be required to fill the newly expanded array as long as the assignment is unambiguous. In these cases the array will be automatically padded with null values:
>> a = [1, 2] a = 1 2 >> a(4) = 5 a = 1 2 0 5 >> a(3, :) = [6, 7, 8, 9] a = 1 2 0 5 0 0 0 0 6 7 8 9 >> a(4, 5) = 10 a = 1 2 0 5 0 0 0 0 0 0 6 7 8 9 0 0 0 0 0 10
For all built-in types, the null value will be appropriate to that object type.
Numeric arrays:
>> a = int32 ([1, 2]) a = 1, 2 >> a(4) = 5 a = 1 2 0 5
Logical arrays:
>> a = [true, false, true] a = 1 0 1 >> d(5) = true d = 1 0 1 0 1
Character arrays:
>> a = "abc" a = abc >> a(5) = "d" a = abcd >> double (a) ans = 97 98 99 0 100
Cell arrays:
>> e = {1, "foo", [3, 4]}; >> e(5) = "bar" e = { [1,1] = 1 [1,2] = foo [1,3] = 3 4 [1,4] = [](0x0) [1,5] = bar }
Struct arrays:
>> a = struct("foo",1,"bar",2); >> a(3) = struct("foo",3,"bar",9) a = 1x3 struct array containing the fields: foo bar >> a.foo ans = 1 ans = [](0x0) ans = 3 >> a.bar ans = 2 ans = [](0x0) ans = 9
Note that Octave currently is unable to concatenate arbitrary object types into arrays. Such behavior must be explicitly defined within the object class or attempts at concatenation will result in an error. See Object Oriented Programming
Assigning an empty matrix ‘[]’ works in most cases to allow you to delete rows or columns of matrices and vectors. See Empty Matrices. For example, given a 4 by 5 matrix A, the assignment
A (3, :) = []
deletes the third row of A, and the assignment
A (:, 1:2:5) = []
deletes the first, third, and fifth columns.
Deleting part of an array object will necessarily resize the object. When the deletion allows for consistent size reduction across a dimension, e.g., one element of a vector, or one row or column of a matrix, the size along that dimension will be reduced while preserving dimensionality. If, however, dimensionality cannot be maintained, the object will be reshaped into a vector following column-wise element ordering:
>> a = [1, 2, 3, 4; 5, 6, 7, 8] a = 1 2 3 4 5 6 7 8 >> a(:, 3) = [] a = 1 2 4 5 6 8 >> a(4) = [] a = 1 5 2 4 8
An assignment is an expression, so it has a value. Thus, z = 1
as an expression has the value 1. One consequence of this is that you
can write multiple assignments together:
x = y = z = 0
stores the value 0 in all three variables. It does this because the
value of z = 0
, which is 0, is stored into y
, and then
the value of y = z = 0
, which is 0, is stored into x
.
This is also true of assignments to lists of values, so the following is a valid expression
[a, b, c] = [u, s, v] = svd (a)
that is exactly equivalent to
[u, s, v] = svd (a) a = u b = s c = v
In expressions like this, the number of values in each part of the expression need not match. For example, the expression
[a, b] = [u, s, v] = svd (a)
is equivalent to
[u, s, v] = svd (a) a = u b = s
The number of values on the left side of the expression can, however, not exceed the number of values on the right side. For example, the following will produce an error.
[a, b, c, d] = [u, s, v] = svd (a); -| error: element number 4 undefined in return list
The symbol ~
may be used as a placeholder in the list of lvalues,
indicating that the corresponding return value should be ignored and not stored
anywhere:
[~, s, v] = svd (a);
This is cleaner and more memory efficient than using a dummy variable.
The nargout
value for the right-hand side expression is not affected.
If the assignment is used as an expression, the return value is a
comma-separated list with the ignored values dropped.
A very common programming pattern is to increment an existing variable with a given value, like this
a = a + 2;
This can be written in a clearer and more condensed form using the
+=
operator
a += 2;
Similar operators also exist for subtraction (-=
),
multiplication (*=
), and division (/=
). An expression
of the form
expr1 op= expr2
is evaluated as
expr1 = (expr1) op (expr2)
where op can be either +
, -
, *
, or /
,
as long as expr2 is a simple expression with no side effects. If
expr2 also contains an assignment operator, then this expression
is evaluated as
temp = expr2 expr1 = (expr1) op temp
where temp is a placeholder temporary value storing the computed result of evaluating expr2. So, the expression
a *= b+1
is evaluated as
a = a * (b+1)
and not
a = a * b + 1
You can use an assignment anywhere an expression is called for. For
example, it is valid to write x != (y = 1)
to set y
to 1
and then test whether x
equals 1. But this style tends to make
programs hard to read. Except in a one-shot program, you should rewrite
it to get rid of such nesting of assignments. This is never very hard.