Functions & probability statements
Reusable code chunks
Repeated calculations can be written once using func:
func llk() {
double sigma = exp(logsigma(1));
for (i = 1:n) {
y(i) ~ dnorm(mu(i), sigma);
}
}
A HOBBS func is a zero-argument reusable code chunk. The translator expands it at each call site rather than treating it as a conventional run-time function.
block logsigma(1) {
logsigma(1) ~ dnorm(0, 2);
llk();
}
Because expansion occurs inside the surrounding block, the chunk can use the block’s index symbols and locally available names. Avoid temporary-name collisions between expanded chunks and surrounding code.
Probability statements
The basic statistical statement is
value(i) ~ distribution(arguments);
It adds the corresponding log density or log probability to the current block target. The same syntax is used for priors and likelihood contributions.
beta(j) ~ dnorm(0, 10);
y(i) ~ dnorm(mu(i), sigma);
gamma(j) ~ dbern(pi);
For multivariate densities, ranges can be used:
u(j,1:2) ~ dmvn(zero2, Sigma_u);
Custom log-density terms
The target can also be modified directly. This makes the built-in distribution list extensible without changing the sampler:
func custom_laplace() {
target += -log(2.0 * b) - fabs(x(i) - mu_i) / b;
}
The model body otherwise remains close to C: scalar declarations, transformations, loops, conditionals, assignments, and numerical expressions can be mixed with probability statements.