Getting started
Introduction
- Basic Functions (Stan User Guide: User Defined Functions)
- Helpful Functions Repository (Lots of Examples)
Example
add.stan
functions {
  real add(real x, real y) {
    return x + y;
  }
  data {
      real x;
  }
  parameters {
      real y;
  }
  transformed parameters {
      real z = add(x, y);
  }
  model {
      y ~ std_normal();
  }
}
Types of User Defined Functions
Basic Type Declarations
Typical variable types. No constraint types like simplex[], cholesky_factor_corr[], etc.!
real foo(real x);
vector foo(real x);
matrix foo(real x);
array[] real foo(real x);
array[ , ] real foo(real x);
array[ , , ] real foo(real x);
...
Void Type
These do not return any value.
void print_hello(real x) {
    print("hello");
}
void increment_lp(real x){
    target += 1;
}
Distribution Type
Keywords _lpdf, _lpmf, _lcdf
functions {
    real my_normal_lpdf(real y, real mu, real sigma) {
        return normal_lpdf(y | mu, sigma);
    }
    real my_normal_lcdf(real y, real mu, real sigma) {
        return normal_lcdf(y | mu, sigma);   
    }
}
// ...
model {
    alpha ~ my_normal(mu, sigma);
    // or target += my_normal_lpdf(alpha | mu, sigma);
    target += my_normal_lcdf(x | mu, sigma);
}
Log-probability Type
Keyword _lp. These can access the log probability accumulator in the transformed parameters or model blocks.
functions {
  vector center_lp(vector beta_raw, real mu, real sigma) {
    beta_raw ~ std_normal();
    sigma ~ cauchy(0, 5);
    mu ~ cauchy(0, 2.5);
    return sigma * beta_raw + mu;
  }
  // ...
}
parameters {
  vector[K] beta_raw;
  real mu_beta;
  real<lower=0> sigma_beta;
  // ...
}
transformed parameters {
  vector[K] beta;
  // ...
  beta = center_lp(beta_raw, mu_beta, sigma_beta);
  // ...
}
Random number Type
Keywork _rng. Works in transformed data and generated quantities blocks.
real normal_lub_rng(real mu, real sigma, real lb, real ub) {
  real p_lb = normal_cdf(lb, mu, sigma);
  real p_ub = normal_cdf(ub, mu, sigma);
  real u = uniform_rng(p_lb, p_ub);
  real y = mu + sigma * inv_Phi(u);
  return y;
}
Recursive Functions
matrix matrix_pow(matrix a, int n);
matrix matrix_pow(matrix a, int n) {
  if (n == 0) {
    return diag_matrix(rep_vector(1, rows(a)));
  } else {
    return a *  matrix_pow(a, n - 1);
  }
}
Although not a type, these require double declaration. Once with the signature and again with the function definition. See Recursive Functions.
Catching Errors
Reject statements
Detect bad or illegal outcomes.
real positive_number(real x) {
    if (x < 0) {
        reject("positive_number(x): x must be positive; found x = ", x);
    }
    return x;
}
Print statements
Need to see what’s happening in the function? Use print statements.
real sqrt_problem (real x) {
    real y = sqrt(x);
    // you forgot to check for negatives 
    // so you're debugging with print 
    // to see what's happening
    print("sqrt_problem: x is ", x, " return is ", y);
    return y;
}
0 Comments for this cheatsheet. Write yours!