# Is this an expected behavior of rand.()?

``````julia> A = zeros(3,3)
3×3 Matrix{Float64}:
0.0  0.0  0.0
0.0  0.0  0.0
0.0  0.0  0.0

julia> true ? A .= rand.() : nothing
3×3 Matrix{Float64}:
0.191487  0.0617435  0.279438
0.47524   0.467929   0.45603
0.212515  0.21998    0.51552

julia> A.= true ? rand.() : 0
3×3 Matrix{Float64}:
0.30043  0.30043  0.30043
0.30043  0.30043  0.30043
0.30043  0.30043  0.30043
``````

The behavior of `A.= true ? rand.() : 0` is equivalent to `A.= true ? rand() : 0`.

I would say yes, because they can be translated to

``````if true
A .= rand.()
else
nothing
end
``````

and

``````for i = 1:length(A)
if true
A[i] = rand.()
else
A[i] = 0
end
end
``````

Note that `rand.()` alone gives only one random number, unless it is used in a broadcast.

2 Likes

I agree with @fatteneder, it is expected. To explain why, your code is an example of how syntactic loop fusion does not fuse across non-broadcasted calls (in this case, ternary `⋯ ? ⋯ : ⋯` is not broadcasted) although it is an admittedly opaque example.

Here’s an excellent blog post on syntactic loop fusion. In brief:

Syntactic loop fusion transforms an expression like `A .= f.(g.(h.(x)))` into a single loop:

``````for i in eachindex(x)
A[i] = f(g(h(x[i])))
end
``````

But loops are not fused across non-broadcasted barriers, so `A .= f.(g(h.(x)))` is equivalent to:

``````temp1 = h.(x) # one loop
temp2 = g(temp1) # no loop
A .= f.(temp2) # another loop
``````

In your case, it might help to rephrase it as it as:

``````ifelse(true, A .= rand.(), nothing)
# vs
A .= ifelse(true, rand.(), 0)
``````

This makes it clearer why the second example results in two separate loops (the first loop is just `rand.()` generating a single number). The first example is one loop, where `rand` is broadcasted to the shape `A`, producing different numbers…

3 Likes

I see, thanks for the clear explanation.

Careful: `ifelse(false, A .= rand.(), nothing)` will still overwrite `A`, because `ifelse` is a function (not special syntax like `if` or `?`) that evaluates all arguments before deciding which one to return.

8 Likes