# Unexpected behavior of similar

I find this behavior of similar unexpected:

``````julia> r = [rand(2, 2) for i in 1:3]

julia> x = similar(r)
3-element Vector{Matrix{Float64}}:
#undef
#undef
#undef

julia> x[1]
Stacktrace:
[1] getindex(A::Vector{Matrix{Float64}}, i1::Int64)
@ Base ./array.jl:801
[2] top-level scope
@ REPL[5]:1
``````

That’s fine because `x[1]` is `undef`. But if I specify the type of the elements, I still get these `undef` that I can’t access to overwrite:

``````julia> x = similar(r, Matrix{Float64})
3-element Vector{Matrix{Float64}}:
#undef
#undef
#undef
``````

How can I fill `x`? What I am trying to do is something like this:

``````r = [rand(2, 2) for i in 1:3]
x = similar(r)
for i in 1:3
x[i] .= rand(2, 2)
end
``````

Just do `x[i] = rand(2, 2)` (without the dot) instead of `x[i] .= rand(2, 2)`. That way you are making the element `x[i]` point to the new matrix that is created by `rand(2, 2)`. By using broadcasting, you try to overwrite the values in the matrix `x[i]`, but it fails because the matrix `x[i]` does not exist.

Maybe I am misunderstanding you, but why do you think that specifying the element type would change things here? Since the original element type is already `Matrix{Float64}`, specifying it again doesn’t change anything.

1 Like

Maybe just

``````julia> similar.(r)
3-element Vector{Matrix{Float64}}:
[0.0 1.37471521e-315; 1.376029345e-315 0.0]
[0.0 1.37471521e-315; 1.376029345e-315 0.0]
[0.0 1.37471521e-315; 1.376029345e-315 0.0]
``````
1 Like

What I had in mind was to apply this function to a vector like `x`:

``````function claytonsample!(matkk, τ; randmat=randmat)
matkk .= randmat
τ == 0 && return matkk

n = size(matkk, 1)
for i in 1:n
v = matkk[i, 2]
u = matkk[i, 1]
matkk[i, 2] = (1 - u^(-τ) + u^(-τ)*v^(-(τ/(1 + τ))))^(-1/τ)
end
return matkk
end

randmat = rand(10, 2)
matkk = similar(randmat)

#this works:
claytonsample!(matkk, 0.3; randmat=randmat)

#this doesn't:
randmat2 = [rand(10, 2) for i in 1:3]
matkk2 = similar(randmat2)

for i in 1:3
claytonsample!(matkk2[i], 0.3; randmat=randmat2[i])
end
``````

With @nilshg proposal, it now works:

``````randmat2 = [rand(10, 2) for i in 1:3]
matkk2 = similar.(randmat2)

for i in 1:3
claytonsample!(matkk2[i], 0.3; randmat=randmat2[i])
end
``````
1 Like