Using the DiffResult API

We are wrapping up the API for a GSOC project and I need some help about how to best integrate this into the existing Julia ecosystem.

From a theoretical point of view, the API needs a simple function ℓ:ℝⁿ→ℝ (log posterior), its gradient ∇ℓ:ℝⁿ→ℝⁿ, and a starting point θ. For the first two, the user currently supplies a model object model, which, among other things (bookkeeping), mostly supports logdensity(model, θ) and loggradient(model, θ). But since both the gradient and the density are frequently needed together, this is wasteful, and something like the DiffResult API could be a good choice. Important: type stability is crucial.

For the actual algorithm, possibly ForwardDiff.jl or ReverseDiff.jl may be used, or some other option (eg manual calculation of derivatives for some simple models). I don’t want the API to commit to either. This should be up to the user.

What I thought about: have an interface which supports

gradient!(result::DiffBase.DiffResult, model, θ)

for model and θ. When defining this method, the user picks the implementation (forward or reverse AD, or manual calculation). Choices and parameters specific to this could be shoved into model (eg ForwardDiff.GradientConfig). The interface calls gradient!, then queries result for value and gradient.

Problem: all methods would need to pass around result in addition to model all the way down. Possible solution: wrap result and model in a single object together, but this looks inelegant.

It is possible that I am not grasping the related APIs well. Any advice would be appreciated.

Maybe the API for optimizers can help? E.g. OnceDifferentiable in https://github.com/JuliaNLSolvers/NLSolversBase.jl