6.11 Higher-Order Functions

There are several expression constructions in Stan that act as higher-order functions.4

The higher-order functions and the signature of their argument functions are listed in the higher-order functions table and the variadic higher-order functions table.

Higher-order Functions Table. Higher-order functions in Stan with their argument function types. The first group of arguments can be a function of parameters or data. The second group of arguments, consisting of a real and integer array in all cases, must be expressions involving only data and literals.

function parameter or data args data args return type
algebra_solver vector, vector real[], int[] vector
algebra_solver_newton vector, vector real[], int[] vector
integrate_1d, real, real, real[] real[], int[] real
integrate_ode_X, real, real[], real[] real[], int[] real[]
map_rect vector, vector real[], int[] vector

For example, the integrate_ode_rk45 function can be used to integrate differential equations in Stan:

functions {
  real[] foo(real t, real[] y, real[] theta, real[] x_r, int[] x_i) {
    ...
...
int<lower=1> T;
real y0[2];
real t0;
real ts[T];
real theta[1];
real x_r[0];
int x_i[0];
...
real y_hat[T, 2] = integrate_ode_rk45(foo, y0, t0, ts, theta, x_r, x_i);

The function argument is foo, the name of the user-defined function; as shown in the higher-order functions table, integrate_ode_rk45 takes a real array, a real, three more real arrays, and an integer array as arguments and returns 2D real array.

Variadic Higher-order Functions Table. Variadic Higher-order functions in Stan with their argument function types. The first group of arguments are restricted in type. The sequence of trailing arguments can be of any length with any types.

function restricted args return type
ode_X, vector, real, real[] vector[]
reduce_sum T[], T1, T2 real

T, T1, and T2 can be any Stan type.

For example, the ode_rk45 function can be used to integrate differential equations in Stan:

functions {
  vector foo(real t, vector y, real theta, vector beta, int[] x_i, int index) {
    ...
...
int<lower=1> T;
vector[2] y0;
real t0;
real ts[T];
real theta;
vector[7] beta;
int x_i[10];
int index;
...
vector[2] y_hat[T] = ode_rk45(foo, y0, t0, ts, theta, beta, x_i, index);

The function argument is foo, the name of the user-defined function. As shown in the variadic higher-order functions table, ode_rk45 takes a real, a vector, a real, a real array, and a sequence of arguments whos types match those at the end of foo and returns an array of vectors.

Functions Passed by Reference

The function argument to higher-order functions is always passed as the first argument. This function argument must be provided as the name of a user-defined or built-in function. No quotes are necessary.

Data-Restricted Arguments

Some of the arguments to higher-order functions are restricted to data. This means they must be expressions containing only data variables, transformed data variables, or literals; the may contain arbitrary functions applied to data variables or literals, but must not contain parameters, transformed parameters, or local variables from any block other than transformed data.

For user-defined functions the qualifier data may be prepended to the type to restrict the argument to data-only variables.


  1. Internally, they are implemented as their own expression types because Stan doesn’t have object-level functional types (yet).↩︎