v0.8.3 tutorial · reusable model code
Declare, overload, and call Stan functions
Organize a model with typed functions, forward declarations, lexical locals, checked overloads, data-only arguments, probability suffixes, and guarded recursion.
Source-compatible function coreDefinition order
Forward-declare before a later definition
functions {
real penalty(real x);
real penalty(real x) { return square(x); }
}
model { target += -0.1 * penalty(theta); }A declaration and definition must have the same return type, name, argument types, dimensions, and data qualifiers. Duplicate or unresolved declarations are compile errors.
Typed dispatch
Use overloads without runtime guessing
functions {
real score(real x) { return square(x); }
real score(vector x) { return dot_product(x, x); }
vector predict(data matrix X, vector beta) { return X * beta; }
}Overload selection uses declared container type and shape, with integer-to-real promotion where unambiguous. A data-qualified argument accepts values proven to originate only from data or transformed data; passing a parameter-dependent expression produces a no-matching-overload diagnostic.
Distribution syntax
Follow Stan suffix and target rules
functions {
real robust_lpdf(real y, real mu) {
return student_t_lpdf(y | 5, mu, 1);
}
real shrink_lp(real x) {
target += normal_lpdf(x | 0, 2);
return 0;
}
}
model {
y ~ robust(mu);
target += shrink_lp(mu);
}_lpdf and _lpmf functions return real and expose sampling-statement shorthand. _lp functions may increment target. The vertical bar in probability calls is accepted.
Finite work
Recursion is supported with a guard
real polynomial_sum(real x, int degree) {
if (degree == 0) return 1;
return pow(x, degree) + polynomial_sum(x, degree - 1);
}Calls have lexical local scope and may recurse, but JDistlib enforces a depth guard so malformed source cannot consume the Java stack indefinitely. Loops have analogous work guards.
Cross the Java boundary explicitly
Bind external declarations or pass functions to solvers
A declaration without a source body may be supplied through ExternalFunctionRegistry. Its Java callback returns an ExternalFunctionResult containing flattened values, result shape, and a full Jacobian; JDistlib inserts it as an atomic reverse node. Tuple arguments/returns participate in ordinary user-function overloads. Function-name arguments are supported by integrate_1d, algebraic solvers, RK45/BDF ODEs, and index-1 DAEs. See examples 34, 35, and 38–41 and the solver tutorial.
Current boundary
Know which services are intentionally narrower
Top-level tuple data/parameters, arrays of tuples, external tuple returns, modern variadic solver signatures, and Stan's parallel reduce_sum/map_rect runtime are not part of the 0.8.3 contract. Unsupported overloads fail explicitly. Examples 11, 14, 15, 29, and 31–41 in the checked Stan catalog are runnable companions.