7.2 Assignment Statement
An assignment statement consists of a variable (possibly multivariate with indexing information) and an expression. Executing an assignment statement evaluates the expression on the right-hand side and assigns it to the (indexed) variable on the left-hand side. An example of a simple assignment is as follows.5
n = 0;
Executing this statement assigns the value of the expression 0
,
which is the integer zero, to the variable n
. For an assignment
to be well formed, the type of the expression on the right-hand side
should be compatible with the type of the (indexed) variable on the
left-hand side. For the above example, because 0
is an
expression of type int
, the variable n
must be declared
as being of type int
or of type real
. If the variable
is of type real
, the integer zero is promoted to a
floating-point zero and assigned to the variable. After the
assignment statement executes, the variable n
will have the
value zero (either as an integer or a floating-point value, depending on
its type).
Syntactically, every assignment statement must be followed by a semicolon. Otherwise, whitespace between the tokens does not matter (the tokens here being the left-hand-side (indexed) variable, the assignment operator, the right-hand-side expression and the semicolon).
Because the right-hand side is evaluated first, it is possible to increment a variable in Stan just as in C++ and other programming languages by writing
n = n + 1;
Such self assignments are not allowed in BUGS, because they induce a cycle into the directed graphical model.
The left-hand side of an assignment may contain indices for array,
matrix, or vector data structures. For instance, if Sigma
is
of type matrix
, then
Sigma[1, 1] = 1.0;
sets the value in the first column of the first row of Sigma
to one.
Assignments to subcomponents of larger multi-variate data structures
are supported by Stan. For example, a
is an array of type
real[ , ]
and b
is an array of type real[]
, then
the following two statements are both well-formed.
a[3] = b;
b = a[4];
Similarly, if x
is a variable declared to have type
row_vector
and Y
is a variable declared as type
matrix
, then the following sequence of statements to swap the
first two rows of Y
is well formed.
x = Y[1];
Y[1] = Y[2];
Y[2] = x;
Lvalue Summary
The expressions that are legal left-hand sides of assignment statements are known as “lvalues.” In Stan, there are only two kinds of legal lvalues,
- a variable, or
- a variable with one or more indices.
To be used as an lvalue, an indexed variable must have at least as many dimensions as the number of indices provided. An array of real or integer types has as many dimensions as it is declared for. A matrix has two dimensions and a vector or row vector one dimension; this also holds for the constrained types, covariance and correlation matrices and their Cholesky factors and ordered, positive ordered, and simplex vectors. An array of matrices has two more dimensions than the array and an array of vectors or row vectors has one more dimension than the array. Note that the number of indices can be less than the number of dimensions of the variable, meaning that the right hand side must itself be multidimensional to match the remaining dimensions.
Multiple Indexes
Multiple indexes, as described in the multi-indexing section, are also permitted on the left-hand side of assignments. Indexing on the left side works exactly as it does for expressions, with multiple indexes preserving index positions and single indexes reducing them. The type on the left side must still match the type on the right side.
Aliasing
All assignment is carried out as if the right-hand side is copied before the assignment. This resolves any potential aliasing issues arising from he right-hand side changing in the middle of an assignment statement’s execution.
Compound Arithmetic and Assignment Statement
Stan’s arithmetic operators may be used in compound arithmetic and assignment operations. For example, consider the following example of compound addition and assignment.
real x = 5;
x += 7; // value of x is now 12
The compound arithmetic and assignment statement above is equivalent to the following long form.
x = x + 7;
In general, the compound form
x op= y
will be equivalent to
x = x op y;
The compound statement will be legal whenever the long form is legal.
This requires that the operation x op y
must itself be well
formed and that the result of the operation be assignable to x
.
For the expression x
to be assignable, it must be an indexed
variable where the variable is defined in the current block. For
example, the following compound addition and assignment statement will
increment a single element of a vector by two.
vector[N] x;
x[3] += 2;
As a further example, consider
matrix[M, M] x;
vector[M] y;
real z;
x *= x; // OK, (x * x) is a matrix
x *= z; // OK, (x * z) is a matrix
x *= y; // BAD, (x * y) is a vector
The supported compound arithmetic and assignment
operations are listed in the compound arithmetic/assignment table; they
are also listed in the index prefaced by operator
, e.g.,
operator+=
.
Compound Arithmetic/Assignment Table. Stan allows compound arithmetic and assignment statements of the forms listed in the table above. The compound form is legal whenever the corresponding long form would be legal and it has the same effect.
operation | compound | unfolded |
---|---|---|
addition | x += y |
x = x + y |
subtraction | x -= y |
x = x - y |
multiplication | x *= y |
x = x * y |
division | x /= y |
x = x / y |
elementwise multiplication | x .*= y |
x = x .* y |
elementwise division | x ./= y |
x = x ./ y |
In versions of Stan before 2.18.0, the operator
<-
was used for assignment rather than using the equal sign=
. The old operator<-
is now deprecated and will print a warning. In the future, it will be removed.↩