# @. weird behavior

**URL:** <https://discourse.julialang.org/t/weird-behavior/34490>\
**Category:** New to Julia\
**Created:** [February 11, 2020, 9:49pm UTC](https://discourse.julialang.org/t/weird-behavior/34490 "2020-02-11T21:49:42Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [February 11, 2020, 9:49pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/1 "2020-02-11T21:49:42Z")

</div>

From `@.`'s documentation:  
“Convert every function call or operator in `expr` into a “dot call” (e.g. convert `f(x)` to `f.(x)` […]  
If you want to avoid adding dots for selected function calls in expr, splice those function calls in with $. […]”

So I find this very weird:

```julia
julia> ones(2,2) == ones.(2,2) # dot call here has no effect, as expected
true

julia> ones(2,2)*rand(2,2) # a regular matrix multiplication
2×2 Array{Float64,2}:
 1.54045 1.12931
 1.54045 1.12931

julia> ones(2,2).*rand(2,2) # a "dot call" multiplication
2×2 Array{Float64,2}:
 0.891492 0.744927
 0.647717 0.384459

julia> @. ones(2,2)*rand(2,2) # should be "dot call" multiplication, but isn't
2×2 Array{Float64,2}:
 1.17028 0.784963
 1.17028 0.784963

julia> @. $ones(2,2)*$rand(2,2) # suddenly this fixes it
2×2 Array{Float64,2}:
 0.946279 0.959486
 0.80436 0.596985

```

What is going on?

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [February 11, 2020, 10:04pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/2 "2020-02-11T22:04:01Z")

</div>

good observation. also:

```julia
julia> @. ones(2,2) .* rand(2,2)
2×2 Array{Float64,2}:
 1.6686 0.527706
 1.6686 0.527706

```

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [February 11, 2020, 10:25pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/3 "2020-02-11T22:25:08Z")

</div>

> [@ric.cioffi](#):
>
> @. ones(2,2)\*rand(2,2)

This is equivalent to `ones.(2,2) .* rand.(2,2)`. This in turn reduces to `broadcast((a,b,c,d) -> ones(a,b) * rand(c,d), 2, 2, 2, 2)`, and since all the arguments (the `(2,2,2,2)`) are just scalars, there’s no broadcasting, the function is just evaluated once at `(2,2,2,2)`, hence you get the matrix multiplication behavior.

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [February 11, 2020, 11:33pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/4 "2020-02-11T23:33:59Z")

</div>

I think my brain is on the verge of exploding haha.

Ok, I understand why there’s no broadcasting and therefore the matrix multiplication behavior.  
I still find it mind-bending that I can do

```julia
a = ones.(2,2)
b = rand.(2,2)
c = a.*b

```

and get the expected behavior, while doing `c = ones.(2,2).*rand.(2,2)` gets me something completely different.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [February 12, 2020, 6:00am UTC](https://discourse.julialang.org/t/weird-behavior/34490/5 "2020-02-12T06:00:15Z")

</div>

The only question you need to ask yourself is, do you want to broadcast all the calls in the expression or not? When you call `a * b`, the only function call is `*`, but in `ones(2,2) * b` there are two function calls, one to `ones` and one to `*`, and the `@.` will broadcast both.

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [February 12, 2020, 4:00pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/6 "2020-02-12T16:00:29Z")

</div>

But that doesn’t seem to be exactly what’s happening.  
In my last example I’m broadcasting all function calls: `ones`, `rand`, and `*`:

```julia
a, b = ones.(2,2), rand.(2,2)
c = a.*b

```

On the other hand, as @marius311 was saying, what happens when I instead do `c = ones.(2,2).*rand.(2,2)` is that – because `ones` and `rand` get fed with scalars – the `*` operator doesn’t get broadcasted. It is this very last thing that I find weird because I’m specifically telling julia to broadcast the multiplication operator.

Here:

```julia
using Random
a, b = ones(2, 2), rand(MersenneTwister(123), 2, 2)
a_br, b_br = @. ones(2, 2), rand(MersenneTwister(123), 2, 2)

a == a_br, b == b_br # true
a .* b == a_br .* b_br # true

c0, c1 = @. a*b, a_br*b_br # this is fine
c_br = @. ones(2, 2)*rand(MersenneTwister(123), 2, 2) # this does it differently
c0 == c1 # obviously true
c0 == c_br # now this is false

```

Again, I understand what is going on in that last `@.` call, but I still find it very counter-intuitive that, because the `ones` and `rand` calls don’t get broadcasted in `broadcast((a,b,c,d) -> ones(a,b)*rand(c,d), 2, 2, 2, 2)`, the `*` call doesn’t get broadcasted either

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 12, 2020, 4:24pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/7 "2020-02-12T16:24:26Z")

</div>

That’s why broadcast has to be a syntax rather than an optimization in this case.

And that’s also why I don’t recommand using `@.`. Especially when you are mixing functions that returns an array and functions that do not.

> [@ric.cioffi](#):
>
> because I’m specifically telling julia to broadcast the multiplication operator.

No, you never tell julia to do that. You are telling julia to broadcast the expression, not `.*`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 12, 2020, 4:30pm UTC](https://discourse.julialang.org/t/weird-behavior/34490/8 "2020-02-12T16:30:19Z")

</div>

> [@ric.cioffi](#):
>
> very counter-intuitive that, because the `ones` and `rand` calls don’t get broadcasted in `broadcast((a,b,c,d) -> ones(a,b)*rand(c,d), 2, 2, 2, 2)` , the `*` call doesn’t get broadcasted either

It is not supposed to — did you read the manual on [fusion](https://docs.julialang.org/en/v1/manual/mathematical-operations/#man-dot-operators-1)? Or see [this blog post](https://julialang.org/blog/2018/05/extensible-broadcast-fusion/).

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [February 13, 2020, 1:23am UTC](https://discourse.julialang.org/t/weird-behavior/34490/9 "2020-02-13T01:23:33Z")

</div>

Very interesting readings.

So, let’s see if I got it right this time.

From using `Meta.@lower` I see that `ones.(2,2).*rand.(2,2)` is basically being “translated” into

```julia
julia> using .Broadcast: materialize, broadcasted

julia> bc = broadcasted(*, broadcasted(ones, 2, 2), broadcasted(rand, 2, 2))
Base.Broadcast.Broadcasted(*, (Base.Broadcast.Broadcasted(ones, (2, 2)), Base.Broadcast.Broadcasted(rand, (2, 2))))

julia> materialize(bc)
2×2 Array{Float64,2}:
 1.08929 0.944512
 1.08929 0.944512

```

here `bc` holds everything necessary to “unfold” the computation, which if I understand correctly is then only performed by the `materialize` call.

Somewhat differently instead, if I call `ones(2,2).*rand(2,2)` this translates into

```julia
julia> bc = broadcasted(*, ones(2,2), rand(2,2))
Base.Broadcast.Broadcasted(*, ([1.0 1.0; 1.0 1.0], [0.19239965952523885 0.8796361629139042; 0.1939935696169941 0.0831963706586214]))

julia> materialize(bc)
2×2 Array{Float64,2}:
 0.1924 0.879636 
 0.193994 0.0831964

```

which I could also achieve by writing

```julia
a, b = broadcasted(ones, 2, 2), broadcasted(rand, 2, 2)
bc = broadcasted(*, materialize(a), materialize(b))
materialize(bc)

```

So, I went and checked how `materialize` works. I’m not entirely sure I understand it but, from what I got, it `instantiate`s the (otherwise lazy) `Broadcasted` object.  
So the difference between calling it only only on the “fused” expression and calling it in each single case is:

- doing `@. ones(2,2)*rand(2,2)` does not “apply” (`instantiate`) any function/object until the very end
- doing `broadcasted(*, ones(2,2), rand(2,2))` instead “`instantiate`s” the two arrays before calling the broadcast operation (though `instantiate` is probably not the correct term here).

I think I got it. I still find it unintuitive from a “high-level” perspective, but at least I understand a bit what’s going on now (which will hopefully prevent bugs in the future).

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 13, 2020, 2:07am UTC](https://discourse.julialang.org/t/weird-behavior/34490/10 "2020-02-13T02:07:27Z")

</div>

> [@ric.cioffi](#):
>
> doing `broadcasted(*, ones(2,2), rand(2,2))` instead “ `instantiate` s” the two arrays before calling the broadcast operation (though `instantiate` is probably not the correct term here).

No. There’s nothingn to “instantiate”, or anything about `ones(2, 2)` an `rand(2, 2)`. Yes you get the same result by doing a no-op broadcast, but that’s not at all what happen when you call `ones` and `rand`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 13, 2020, 7:05am UTC](https://discourse.julialang.org/t/weird-behavior/34490/11 "2020-02-13T07:05:48Z")

</div>

I think you are getting sidetracked here by conflating the _semantics_ of broadcasting with the _implementation_.

The latter is a very elegant part of `Base` and exemplifies a lot of advanced techniques so it is worth studying, but the semantics are very simple: in this particular case, mostly equivalent to

```julia
map((a,b,c,d) -> ones(a,b)*rand(c,d), 2, 2, 2, 2)

```

because numbers are iterable collections containing themselves.
