Calling one user defined function from within another function

I’m trying to write a function that returns an integrated quantity. And so, it requires that a function for the integrand be defined. However, I’m not succeeding in calling one function from within another.

If I define them separately, with forward declaration:

  real integrand(real x, real xc, real[] theta);
  
  real beta_diff(real[] theta);
  
  real integrand(real x, real xc, real[] theta) {
    return beta_lpdf(x | theta[1], theta[2]) + beta_lcdf(x | theta[3], theta[4]);
  }
  
  real beta_diff(real[] theta){
    return integrate_1d(integrand, 0, 1, theta)
  }

I get: variable “integrand” does not exist.

If I try to define the integrand function within the beta_diff function:

  real beta_diff(real[] theta){
    
    real integrand(real x, real xc, real[] theta) {
      return beta_lpdf(x | theta[1], theta[2]) + beta_lcdf(x | theta[3], theta[4]);
    }
    
    return integrate_1d(integrand, 0, 1, theta)
  }

I get a parser error.

Any ideas? Is this possible, or can I work with only non nested functions and have to do all the rest within the model block?

Thanks!

This code compiles (I doubt the model makes a lot of sense, but whatevs):

functions {
  real integrand(real x, real xc, real[] theta, real[] x_r, int[] x_i) {
    return beta_lpdf(x | theta[1], theta[2]) + beta_lcdf(x | theta[3], theta[4]);
  }

  real beta_diff(real[] theta, real[] x_r, int[] x_i) {
    return integrate_1d(integrand, 0, 1, theta, x_r, x_i, 1e-8);
  }
}

data {
}

transformed data {
  real x_r[0];
  int x_i[0];
}

parameters {
  real theta[4];
}

model {
  target += beta_diff(theta, x_r, x_i);
}

Things to note:

  1. The signature of the integrand function is strict. You need to have the x_r and x_i arguments there even if you aren’t using them

  2. I think way I added x_r and x_i as transformed data and passed them through everything is the easiest way to not have x_r and x_i. Apologies for the verbosity.

  3. The last argument to integrate_1d (1e-8 here) is a relative tolerance. It should be optional but wasn’t compiling for me when I didn’t include it. Leave it for now. I’m making an issue for this.