31.6 Parentheses and Brackets
Optional Parentheses for Single-Statement Blocks
Single-statement blocks can be rendered in one of two ways. The fully explicit bracketed way is as follows.
for (n in 1:N) {
y[n] ~ normal(mu,1);
}
The following statement without brackets has the same effect.
for (n in 1:N)
y[n] ~ normal(mu,1);
Single-statement blocks can also be written on a single line, as in the following example.
for (n in 1:N) y[n] ~ normal(mu,1);
These can be much harder to read than the first example. Only use this style if the statement is simple, as in this example. Unless there are many similar cases, it’s almost always clearer to put each sampling statement on its own line.
Conditional and looping statements may also be written without brackets.
The use of for loops without brackets can be dangerous. For instance, consider this program.
for (n in 1:N)
z[n] ~ normal(nu,1);
y[n] ~ normal(mu,1);
Because Stan ignores whitespace and the parser completes a statement as eagerly as possible (just as in C++), the previous program is equivalent to the following program.
for (n in 1:N) {
z[n] ~ normal(nu,1);
}
y[n] ~ normal(mu,1);
Parentheses in Nested Operator Expressions
The preferred style for operators minimizes parentheses. This reduces clutter in code that can actually make it harder to read expressions. For example, the expression a + b * c
is preferred to the equivalent a + (b * c)
or (a + (b * c))
. The operator precedences and associativities follow those of pretty much every programming language including Fortran, C++, R, and Python; full details are provided in the reference manual.
Similarly, comparison operators can usually be written with minimal bracketing, with the form y[n] > 0 || x[n] != 0
preferred to the bracketed form (y[n] > 0) || (x[n] != 0)
.
No Open Brackets on Own Line
Vertical space is valuable as it controls how much of a program you can see. The preferred Stan style is as shown in the previous section, not as follows.
for (n in 1:N)
{
y[n] ~ normal(mu,1);
}
This also goes for parameters blocks, transformed data blocks, which should look as follows.
transformed parameters {
real sigma;
...
}