# Type instability when evaluating prior distributions

When looking at the `@code_warntype` output of the following function

``````using Distributions
const priors = [ Normal(0, 1), Beta(2, 5)]
const pars = [2.0, 0.9]

function prioreval_test(priors, pars::Vector{Float64})

if all(insupport.(priors, pars))
log_priorval = sum(logpdf.(priors, pars))
alarm = false
else
log_priorval = -Inf
alarm = true
end

return log_priorval, alarm
end

@code_warntype prioreval_test(priors, pars)
``````

I find that it is not type stable

``````Body::Tuple{Any,Bool}
3  1 ββ %1   = (Base.arraysize)(priors, 1)::Int64                                                                              ββ»β·β·β·β·β·         materialize
β    %2   = (Base.slt_int)(%1, 0)::Bool                                                                                     βββ»β·β·β·           instantiate
β    %3   = (Base.ifelse)(%2, 0, %1)::Int64                                                                                 ββββββββββ        combine_axes
β    %4   = %new(Base.OneTo{Int64}, %3)::Base.OneTo{Int64}                                                                  βββββββββ          broadcast_axes
β    %5   = (Base.arraysize)(pars, 1)::Int64                                                                                ββββββ»β·β·            broadcast_axes
β    %6   = (Base.slt_int)(%5, 0)::Bool                                                                                     βββββββ»β·β·β·           axes
β    %7   = (Base.ifelse)(%6, 0, %5)::Int64                                                                                 βββββββββββ           map
β    %8   = %new(Base.OneTo{Int64}, %7)::Base.OneTo{Int64}                                                                  ββββββββββ             Type
β    %9   = (%7 === %3)::Bool                                                                                               ββββββ»β·β·β·β·          _bcs
β    %10  = (Base.and_int)(true, %9)::Bool                                                                                  βββββββ»              _bcs1
ββββ        goto #3 if not %10                                                                                              ββββββββ              _bcsm
2 ββ        goto #4                                                                                                         ββββββββ
3 ββ %13  = (%3 === 1)::Bool                                                                                                βββββββββ»              ==
ββββ        goto #4                                                                                                         ββββββββ
4 ββ %15  = Ο (#2 => %10, #3 => %13)::Bool                                                                                  βββββββ
ββββ        goto #6 if not %15                                                                                              βββββββ
5 ββ        goto #12                                                                                                        βββββββ
6 ββ %18  = (%3 === %7)::Bool                                                                                               βββββββββ»β·             ==
β    %19  = (Base.and_int)(true, %18)::Bool                                                                                 ββββββββββ»              &
ββββ        goto #8 if not %19                                                                                              ββββββββ
7 ββ        goto #9                                                                                                         ββββββββ
8 ββ %22  = (%7 === 1)::Bool                                                                                                βββββββββ»              ==
ββββ        goto #9                                                                                                         ββββββββ
9 ββ %24  = Ο (#7 => %19, #8 => %22)::Bool                                                                                  βββββββ
ββββ        goto #11 if not %24                                                                                             βββββββ
10 β        goto #12                                                                                                        βββββββ
11 β %27  = %new(Base.DimensionMismatch, "arrays could not be broadcast to a common size")::DimensionMismatch               ββββββββ»              Type
β           (Base.Broadcast.throw)(%27)                                                                                     βββββββ
ββββ        \$(Expr(:unreachable))                                                                                           βββββββ
12 β %30  = Ο (#5 => %7, #10 => %3)::Int64                                                                                  ββββββ
β    %31  = Ο (#5 => %7, #10 => %3)::Int64                                                                                  ββββββ
β    %32  = Ο (#5 => %7, #10 => %3)::Int64                                                                                  ββββββ
β    %33  = Ο (#5 => %7, #10 => %3)::Int64                                                                                  ββββββ
β    %34  = Ο (#5 => %8, #10 => %4)::Base.OneTo{Int64}                                                                      ββββββ
β    %35  = (Core.tuple)(%34)::Tuple{Base.OneTo{Int64}}                                                                     ββββββ
ββββ        goto #13                                                                                                        ββββββ
13 β        goto #14                                                                                                        βββββ
14 β        goto #15                                                                                                        ββββ
15 β        goto #16                                                                                                        βββ»              instantiate
16 β %40  = (Base.arraysize)(priors, 1)::Int64                                                                              ββββ»β·β·β·β·β·β·β·       preprocess
β    %41  = (Base.slt_int)(%40, 0)::Bool                                                                                    βββββ»β·β·β·           preprocess_args
β    %42  = (Base.ifelse)(%41, 0, %40)::Int64                                                                               ββββββββββββββ      preprocess
β    %43  = (%42 === 1)::Bool                                                                                               βββββββ»β·β·            extrude
β    %44  = (Base.not_int)(%43)::Bool                                                                                       ββββββββ»              newindexer
β    %45  = (Core.tuple)(%44)::Tuple{Bool}                                                                                  ββββββββββ             shapeindexer
β    %46  = (Core.tuple)(1)::Tuple{Int64}                                                                                   ββββββββββ              _newindexer
β    %47  = %new(Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}}, priors, %45, %46)::Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}}
β    %48  = (Base.arraysize)(pars, 1)::Int64                                                                                βββββββ»β·β·β·β·β·         preprocess
β    %49  = (Base.slt_int)(%48, 0)::Bool                                                                                    ββββββββ»β·β·β·           extrude
β    %50  = (Base.ifelse)(%49, 0, %48)::Int64                                                                               βββββββββββββββ        newindexer
β    %51  = (%50 === 1)::Bool                                                                                               ββββββββββ»β·β·            shapeindexer
β    %52  = (Base.not_int)(%51)::Bool                                                                                       βββββββββββ»              _newindexer
β    %53  = (Core.tuple)(%52)::Tuple{Bool}                                                                                  βββββββββββ
β    %54  = (Core.tuple)(1)::Tuple{Int64}                                                                                   βββββββββββ
β    %55  = %new(Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}, pars, %53, %54)::Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}
β    %56  = (Core.tuple)(%47, %55)::Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}
β    %57  = %new(Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(insupport),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}, Distributions.insupport, %56, %35)::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(insupport),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}
β    %58  = (Base.slt_int)(%30, 1)::Bool                                                                                    ββββ»β·β·β·           iterate
ββββ        goto #18 if not %58                                                                                             ββββ
17 β        goto #19                                                                                                        ββββ
18 β        goto #19                                                                                                        ββββ
19 β %62  = Ο (#17 => true, #18 => false)::Bool                                                                             βββ
β    %63  = Ο (#18 => 1)::Int64                                                                                             βββ
β    %64  = Ο (#18 => 1)::Int64                                                                                             βββ
ββββ        goto #21 if not %62                                                                                             βββ
20 β %66  = \$(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Any,1}, svec(Any, Int64), :(:ccall), 2, Array{Any,1}, :(%31), :(%31)))::Array{Any,1}lar
ββββ        goto #31                                                                                                        βββ
21 β        goto #26 if not false                                                                                           ββββ»              getindex
22 β %69  = (Base.sle_int)(1, %63)::Bool                                                                                    βββββ»β·β·            checkbounds
β    %70  = (Base.sle_int)(%63, %32)::Bool                                                                                  ββββββββ            checkbounds_indices
β    %71  = (Base.and_int)(%69, %70)::Bool                                                                                  βββββββ»              checkindex
β    %72  = (Base.and_int)(%71, true)::Bool                                                                                 βββββββ»              &
ββββ        goto #24 if not %72                                                                                             βββββ
23 β        goto #25                                                                                                        βββββ
24 β %75  = Base.throw_boundserror::typeof(Base.throw_boundserror)                                                          βββββ
β    %76  = (Core.tuple)(%63)::Tuple{Int64}                                                                                 βββββ
β           invoke %75(%57::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(insupport),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}, %76::Tuple{Int64})
ββββ        \$(Expr(:unreachable))                                                                                           βββββ
25 β        nothing                                                                                                         β
26 β %80  = (Base.Broadcast.ifelse)(%44, %63, 1)::Int64                                                                     βββββ»β·β·β·           _broadcast_getindex
β    %81  = (Base.arrayref)(false, priors, %80)::Distribution{Univariate,Continuous}                                        ββββββ»              _getindex
β    %82  = (Base.Broadcast.ifelse)(%52, %63, 1)::Int64                                                                     βββββββ»β·             _getindex
β    %83  = (Base.arrayref)(false, pars, %82)::Float64                                                                      ββββββββ»              _broadcast_getindex
β    %84  = (Distributions.insupport)(%81, %83)::Any                                                                        ββββββ»              _broadcast_getindex_evalf
ββββ        goto #27                                                                                                        ββββ
27 β %86  = (Base.Broadcast.typeof)(%84)::DataType                                                                          βββ»              copy
β    %87  = (isa)(%86, Type{Bool})::Bool                                                                                    βββ
ββββ        goto #29 if not %87                                                                                             βββ
28 β %89  = invoke BitArray{1}(\$(QuoteNode(array initializer with undefined values))::UndefInitializer, %33::Int64)::BitArray{1}β·β·            similar
ββββ        goto #30                                                                                                        βββ
29 β %91  = (Base.Broadcast.similar)(%57, %86)::Any                                                                         βββ
ββββ        goto #30                                                                                                        βββ
30 β %93  = Ο (#28 => %89, #29 => %91)::Any                                                                                 βββ
β           (Base.setindex!)(%93, %84, %63)                                                                                 βββ
β    %95  = (Base.Broadcast.copyto_nonleaf!)(%93, %57, %34, %64, 1)::Any                                                    βββ
ββββ        goto #31                                                                                                        βββ
31 β %97  = Ο (#20 => %66, #30 => %95)::Any                                                                                 ββ
ββββ        goto #32                                                                                                        ββ
32 β %99  = (Main.all)(%97)::Any                                                                                            β
ββββ        goto #65 if not %99                                                                                             β
4  33 β %101 = (Base.arraysize)(priors, 1)::Int64                                                                              ββ»β·β·β·β·β·         materialize
β    %102 = (Base.slt_int)(%101, 0)::Bool                                                                                   βββ»β·β·β·           instantiate
β    %103 = (Base.ifelse)(%102, 0, %101)::Int64                                                                             ββββββββββ        combine_axes
β    %104 = %new(Base.OneTo{Int64}, %103)::Base.OneTo{Int64}                                                                βββββββββ          broadcast_axes
β    %105 = (Base.arraysize)(pars, 1)::Int64                                                                                ββββββ»β·β·            broadcast_axes
β    %106 = (Base.slt_int)(%105, 0)::Bool                                                                                   βββββββ»β·β·β·           axes
β    %107 = (Base.ifelse)(%106, 0, %105)::Int64                                                                             βββββββββββ           map
β    %108 = %new(Base.OneTo{Int64}, %107)::Base.OneTo{Int64}                                                                ββββββββββ             Type
β    %109 = (%107 === %103)::Bool                                                                                           ββββββ»β·β·β·β·          _bcs
β    %110 = (Base.and_int)(true, %109)::Bool                                                                                βββββββ»              _bcs1
ββββ        goto #35 if not %110                                                                                            ββββββββ              _bcsm
34 β        goto #36                                                                                                        ββββββββ
35 β %113 = (%103 === 1)::Bool                                                                                              βββββββββ»              ==
ββββ        goto #36                                                                                                        ββββββββ
36 β %115 = Ο (#34 => %110, #35 => %113)::Bool                                                                              βββββββ
ββββ        goto #38 if not %115                                                                                            βββββββ
37 β        goto #44                                                                                                        βββββββ
38 β %118 = (%103 === %107)::Bool                                                                                           βββββββββ»β·             ==
β    %119 = (Base.and_int)(true, %118)::Bool                                                                                ββββββββββ»              &
ββββ        goto #40 if not %119                                                                                            ββββββββ
39 β        goto #41                                                                                                        ββββββββ
40 β %122 = (%107 === 1)::Bool                                                                                              βββββββββ»              ==
ββββ        goto #41                                                                                                        ββββββββ
41 β %124 = Ο (#39 => %119, #40 => %122)::Bool                                                                              βββββββ
ββββ        goto #43 if not %124                                                                                            βββββββ
42 β        goto #44                                                                                                        βββββββ
43 β %127 = %new(Base.DimensionMismatch, "arrays could not be broadcast to a common size")::DimensionMismatch               ββββββββ»              Type
β           (Base.Broadcast.throw)(%127)                                                                                    βββββββ
ββββ        \$(Expr(:unreachable))                                                                                           βββββββ

...

%new(Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}}, priors, %145, %146)::Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}}
β    %148 = (Base.arraysize)(pars, 1)::Int64                                                                                βββββββ»β·β·β·β·β·         preprocess
β    %149 = (Base.slt_int)(%148, 0)::Bool                                                                                   ββββββββ»β·β·β·           extrude
β    %150 = (Base.ifelse)(%149, 0, %148)::Int64                                                                             βββββββββββββββ        newindexer
β    %151 = (%150 === 1)::Bool                                                                                              ββββββββββ»β·β·            shapeindexer
β    %152 = (Base.not_int)(%151)::Bool                                                                                      βββββββββββ»              _newindexer
β    %153 = (Core.tuple)(%152)::Tuple{Bool}                                                                                 βββββββββββ
β    %154 = (Core.tuple)(1)::Tuple{Int64}                                                                                   βββββββββββ
β    %155 = %new(Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}, pars, %153, %154)::Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}
β    %156 = (Core.tuple)(%147, %155)::Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}
β    %157 = %new(Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(logpdf),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}, Distributions.logpdf, %156, %135)::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(logpdf),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}
β    %158 = (Base.slt_int)(%130, 1)::Bool                                                                                   ββββ»β·β·β·           iterate
ββββ        goto #50 if not %158                                                                                            ββββ
49 β        goto #51                                                                                                        ββββ
50 β        goto #51                                                                                                        ββββ
51 β %162 = Ο (#49 => true, #50 => false)::Bool                                                                             βββ
β    %163 = Ο (#50 => 1)::Int64                                                                                             βββ
β    %164 = Ο (#50 => 1)::Int64                                                                                             βββ
ββββ        goto #53 if not %162                                                                                            βββ
52 β %166 = \$(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Any,1}, svec(Any, Int64), :(:ccall), 2, Array{Any,1}, :(%131), :(%131)))::Array{Any,1}r
ββββ        goto #63                                                                                                        βββ
53 β        goto #58 if not false                                                                                           ββββ»              getindex
54 β %169 = (Base.sle_int)(1, %163)::Bool                                                                                   βββββ»β·β·            checkbounds
β    %170 = (Base.sle_int)(%163, %132)::Bool                                                                                ββββββββ            checkbounds_indices
β    %171 = (Base.and_int)(%169, %170)::Bool                                                                                βββββββ»              checkindex
β    %172 = (Base.and_int)(%171, true)::Bool                                                                                βββββββ»              &
ββββ        goto #56 if not %172                                                                                            βββββ
55 β        goto #57                                                                                                        βββββ
56 β %175 = Base.throw_boundserror::typeof(Base.throw_boundserror)                                                          βββββ
β    %176 = (Core.tuple)(%163)::Tuple{Int64}                                                                                βββββ
β           invoke %175(%157::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(logpdf),Tuple{Base.Broadcast.Extruded{Array{Distribution{Univariate,Continuous},1},Tuple{Bool},Tuple{Int64}},Base.Broadcast.Extruded{Array{Float64,1},Tuple{Bool},Tuple{Int64}}}}, %176::Tuple{Int64})
ββββ        \$(Expr(:unreachable))                                                                                           βββββ
57 β        nothing                                                                                                         β
58 β %180 = (Base.Broadcast.ifelse)(%144, %163, 1)::Int64                                                                   βββββ»β·β·β·           _broadcast_getindex
β    %181 = (Base.arrayref)(false, priors, %180)::Distribution{Univariate,Continuous}                                       ββββββ»              _getindex
β    %182 = (Base.Broadcast.ifelse)(%152, %163, 1)::Int64                                                                   βββββββ»β·             _getindex
β    %183 = (Base.arrayref)(false, pars, %182)::Float64                                                                     ββββββββ»              _broadcast_getindex
β    %184 = (Distributions.logpdf)(%181, %183)::Any                                                                         ββββββ»              _broadcast_getindex_evalf
ββββ        goto #59                                                                                                        ββββ
59 β %186 = (Base.Broadcast.typeof)(%184)::DataType                                                                         βββ»              copy
β    %187 = (isa)(%186, Type{Bool})::Bool                                                                                   βββ
ββββ        goto #61 if not %187                                                                                            βββ
60 β %189 = invoke BitArray{1}(\$(QuoteNode(array initializer with undefined values))::UndefInitializer, %133::Int64)::BitArray{1}β·            similar
ββββ        goto #62                                                                                                        βββ
61 β %191 = (Base.Broadcast.similar)(%157, %186)::Any                                                                       βββ
ββββ        goto #62                                                                                                        βββ
62 β %193 = Ο (#60 => %189, #61 => %191)::Any                                                                               βββ
β           (Base.setindex!)(%193, %184, %163)                                                                              βββ
β    %195 = (Base.Broadcast.copyto_nonleaf!)(%193, %157, %134, %164, 1)::Any                                                βββ
ββββ        goto #63                                                                                                        βββ
63 β %197 = Ο (#52 => %166, #62 => %195)::Any                                                                               ββ
ββββ        goto #64                                                                                                        ββ
64 β %199 = (Main.sum)(%197)::Any                                                                                           β
5  ββββ        goto #66                                                                                                        β
65 β        nothing                                                                                                         β
11 66 β %202 = Ο (#64 => %199, #65 => -Inf)::Any                                                                               β
β    %203 = Ο (#64 => false, #65 => true)::Bool                                                                             β
β    %204 = (Core.tuple)(%202, %203)::Tuple{Any,Bool}                                                                       β
ββββ        return %204
``````

I can force the output to Float64 by setting the last line to `return log_priorval::Float64, alarm` but I would like to understand where the type instability is coming from. It has to be the if/else statement but I donβt see why as `typeof(Inf)`is also `Float64`.

Thanks for your help.

1 Like

Since `priors` is a vector of heterogeneous elements (`Normal` and `Beta`), it does not have a concrete element type. The quickest fix is probably using tuples, and then I would do the same for `pars`. Eg

``````using Distributions
const priors = (Normal(0, 1), Beta(2, 5))
const pars = (2.0, 0.9)

function prioreval_test(priors, pars)
if all(insupport.(priors, pars))
log_priorval = sum(logpdf.(priors, pars))
alarm = false
else
log_priorval = -Inf
alarm = true
end

return log_priorval, alarm
end

@code_warntype prioreval_test(priors, pars)
``````

That said, I would recommend you use `NamedTuple`s for parameters, which can avoid order mixups.

3 Likes

also, note that outside the support, you get `-Inf` automatically for the `logpdf`, eg

``````julia> logpdf(Beta(0.1, 0.7), -9)
-Inf
``````

so testing for it separately may not be necessary.

1 Like

Thanks Tamas, thatβs very helpful. Just two quick follow-ups so that I understand this better.

1. (a) Why does it matter for type stability that the `priors` vector contains two different distributions? The outcome of `sum(logpdf.())` will always be a `Float64` scalar. (b) I tried using a tuple for `priors` and a vector for `pars` but that has the same issues as two vectors. Is that just the interplay between the two that then screws up type inference?

2. I can easily construct the priors as a tuple (I use Flatten.jl and that allows to flatten the struct into tuple or vector). But the parameter vector comes directly from the optimizer (using Optim.jl). If I understand it correctly, Optim only outputs (and accepts) arrays. Of course I could transform the vector into a tuple but is there a smarter way?

Again, thanks for your help.

``````using Distributions
const priors = [ Normal(0, 1), Beta(2, 5)]
const pars = [2.0, 0.9]

struct MyDegenerateDistribution <: Distributions.ContinuousUnivariateDistribution end
Distributions.logpdf(::MyDegenerateDistribution, ::Float64) = big(42)
Distributions.insupport(::MyDegenerateDistribution, ::Real) = true

push!(priors, MyDegenerateDistribution())
push!(pars, Inf)
``````

Then,

``````julia> isa.(priors, Distributions.ContinuousUnivariateDistribution)
3-element BitArray{1}:
true
true
true

julia> prioreval_test(priors, pars)
(33.1665579608234732944538336596451699733734130859375, false)

julia> typeof(ans)
Tuple{BigFloat,Bool}
``````

Our answer is a BigFloat!
Or,

``````julia> using StaticArrays

julia> Distributions.logpdf(::MyDegenerateDistribution, ::Float64) = @SMatrix randn(3,3)

julia> prioreval_test(priors, pars)
([-9.15028 -8.84753 -7.32728; -9.23861 -8.53093 -9.21451; -9.76463 -8.44686 -6.88402], false)
``````

Even worse, `sum(logpdf.())` doesnβt have to be defined:

``````julia> Distributions.logpdf(::MyDegenerateDistribution, ::Float64) = "I don't play by the rules!"

julia> prioreval_test(priors, pars)
ERROR: MethodError: no method matching +(::Float64, ::String)
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any...) at operators.jl:521
+(::Float64, ::Float64) at float.jl:395
+(::AbstractFloat, ::Bool) at bool.jl:114
...
Stacktrace:
[1] add_sum(::Float64, ::String) at ./reduce.jl:21
[2] _mapreduce(::typeof(identity), ::typeof(Base.add_sum), ::IndexLinear, ::Array{Any,1}) at ./reduce.jl:316
[3] _mapreduce_dim at ./reducedim.jl:308 [inlined]
[4] #mapreduce#549 at ./reducedim.jl:304 [inlined]
[5] mapreduce at ./reducedim.jl:304 [inlined]
[6] _sum at ./reducedim.jl:653 [inlined]
[7] _sum at ./reducedim.jl:652 [inlined]
[8] #sum#551 at ./reducedim.jl:648 [inlined]
[9] sum(::Array{Any,1}) at ./reducedim.jl:648
[10] prioreval_test(::Array{Distribution{Univariate,Continuous},1}, ::Array{Float64,1}) at ./REPL[21]:4
[11] top-level scope at none:0
``````

While it is hard to think of a good reason for anyone to do that, the compilerβs job is producing valid code. Because it is possible to do this, the compiler needs to generate code able to handle it.

In Tamas_Papps version, with the tuples, the function can specialize one each individual types. Receiving just the Beta and Normal distribution, the compiler is guaranteed silliness like these examples arenβt possible.

3 Likes

a) Vectors are fast if they contain one type of data, otherwise data is boxed as ANY at some point which requires a lot more native code to handle (although small Union vectors are also pretty fast these days).
b) Good to see someone using Flatten.jl for this! Tuple is the default output for this very reason - the vector is just splatted from the tuple for convenience. I should put a warning somewhere in the readme about type stability. For the pars it seems strange that a vector creates type instability, as itβs all Float64. But itβs probably something to do with how broadcast is compiled when given a tuple and a vector. My answer to this kind of type instability is often to use recursion instead of for loops or broadcast. But you could just splat the vector to a tuple here.

As for Optim only working with Vectors itβs a broader problem I would also like to see addressed more often - accepting tuples instead of vectors for parameter lists. This would mean lists of prior distributions and parameters with different Unitful units could be type stable.

1 Like

I wrote TransformVariables precisely for this. It can also transform an unconstrained real to a constrained subset, eg

``````using TransformVariables
t = as((x = asβ, a = asπ))
dimension(t)
t([0.1, 0.2])
``````
1 Like

Thanks everyone! This helped me a lot in understanding the issue.

Please read my reply above again, the answer is at the beginning.

Also, please do invest some effort into reading answers in a topic before pinging people directly.