I am calculating a sum of values returned by a function, which is supposed to be type stable. The function may be costly, and returns values that are either finite or
-Inf. In case of
-Inf, I would like to return early.
MWE (which is of course not costly, the first version does not return early):
observation_logdensity(μ, x) = x > μ ? -abs2(x - μ) : oftype(promote(x, μ), -Inf) sample_logdensity1(μ, xs) = sum(observation_logdensity(μ, x) for x in xs)
Now I am wondering how to program what I want, so that the accumulator does not change type. The function can return a
<: Real type (in a type-stable way), especially
ForwardDiff.Dual. I would like to have a way to figure out the accumulator type. This version does not, so the type changes inevitably:
function sample_logdensity2(μ, xs) total = 0 # in general, I don't know the return type of observation_logdensity for x in xs total += observation_logdensity(μ, x) total == -Inf && return total # terminate early end total end
This version should figure it out (if
observation_logdensity is type stable), but it is cumbersome:
function sample_logdensity3(μ, xs) isempty(xs) && return -Inf total = observation_logdensity(μ, first(xs)) for x in Iterators.drop(xs, 1) total += observation_logdensity(μ, x) total == -Inf && return total # terminate early end total end
I wonder if there is a way to write it in a more compact way idiomatically.
xs can be any iterable.