Creating an Array of Distribution Objects

I’m just getting started using Julia. My version is 1.0.3 on Ubuntu 16.04. I was trying to create an array of Normal Distribution objects in the REPL using a for loop as follows:

using Distributions
means = 10*rand(10)
d = []
for j = 1:size(means,1)
       append!(d, Normal(means[j]))
end

However, the code threw the following error:

ERROR: MethodError: no method matching iterate(::Normal{Float64})
Closest candidates are:
  iterate(::Core.SimpleVector) at essentials.jl:589
  iterate(::Core.SimpleVector, ::Any) at essentials.jl:589
  iterate(::ExponentialBackOff) at error.jl:171
  ...
Stacktrace:
 [1] zip_iterate(::UnitRange{Int64}, ::Normal{Float64}, ::Tuple{}, ::Tuple{}) at ./iterators.jl:304
 [2] iterate at ./iterators.jl:320 [inlined]
 [3] _append!(::Array{Any,1}, ::Base.HasLength, ::Normal{Float64}) at ./array.jl:909
 [4] append!(::Array{Any,1}, ::Normal{Float64}) at ./array.jl:902
 [5] top-level scope at ./REPL[58]:2 [inlined]
 [6] top-level scope at ./none:0

Not quite sure what the problem is. Can Distribution objects not be stored in arrays?

If you’re adding a single item to an array, use push! instead of append! (which is meant for adding a collection to a preexisting collection). You could also write it as such:

julia> [Normal(μ) for μ in 10rand(10)]
10-element Array{Normal{Float64},1}:
 Normal{Float64}(μ=8.259182894319487, σ=1.0)  
 Normal{Float64}(μ=5.722960970066662, σ=1.0)  
 Normal{Float64}(μ=4.906795769403773, σ=1.0)  
 ...
1 Like

This approach also has the benefit of being type stable, which will be more performant. Your type was Array{Any,1}, whereas the type above is Array{Normal{Float64},1}.

3 Likes

Excellent! Works perfectly, and much cleaner syntax. Thank you!