# @. x-y? x : y broadcasting does not work?

**URL:** <https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903>\
**Category:** New to Julia\
**Created:** [June 14, 2021, 6:32pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903 "2021-06-14T18:32:46Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 14, 2021, 6:32pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/1 "2021-06-14T18:32:46Z")

</div>

I don’t quite get why these broadcasting operations do not work:

```julia
julia> x = rand(3); y = rand(3);

julia> f(x,y) = @. (x-y > 0.5 ? x : y )
f (generic function with 1 method)

julia> f(x,y)
ERROR: TypeError: non-boolean (BitVector) used in boolean context
Stacktrace:
 [1] f(x::Vector{Float64}, y::Vector{Float64})
   @ Main ./REPL[38]:1
 [2] top-level scope
   @ REPL[39]:1

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 14, 2021, 6:35pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/2 "2021-06-14T18:35:23Z")

</div>

Because it’s not supported. It’s the same as trying to do

```nohighlight
@. if x-y > 0.5
    x
else
    y
end

```

You can use `@. ifelse(x-y > 0.5, x, y)` instead.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2021, 6:38pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/3 "2021-06-14T18:38:28Z")

</div>

This could be supported in the same way that `.&&` and `.||` support was added, but it just has not yet been attempted as far as I’m aware.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 14, 2021, 6:43pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/4 "2021-06-14T18:43:06Z")

</div>

Maaaaaybe. It’s a little stranger than `.&&` and `.||`. It (currently) is syntacticly identical to the `if` statement, and we don’t support `if.` or `.if`. Are `a .? b : c` and `a ? b .: c` errors? We also don’t support `[1,2,3] .: [8,9,10]`, and I think there’s strange parsing ambiguities around `.:` in general.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 14, 2021, 6:44pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/5 "2021-06-14T18:44:37Z")

</div>

> [@mbauman](#):
>
> You can use `ifelse.(x-y > 0.5, x, y)` instead.

It seems that I have to add a dot to the minus there:

```julia
julia> f(x,y) = ifelse.(x - y > 0.5, x, y)
f (generic function with 1 method)

julia> f(x,y)
ERROR: MethodError: no method matching isless(::Float64, ::SVector{3, Float64})

```

while

```julia
julia> f(x,y) = ifelse.(x - y .> 0.5, x, y)
f (generic function with 1 method)

julia> f(x,y)
3-element SVector{3, Float64} with indices SOneTo(3):
 -0.636700731442766
  0.16919692261464525
 -0.3143986886849526

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 14, 2021, 6:47pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/6 "2021-06-14T18:47:50Z")

</div>

Yeah, sorry, I should’ve just `@.`'ed the entire expression. Edited above.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 14, 2021, 6:49pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/7 "2021-06-14T18:49:33Z")

</div>

Actually what I was trying to do is this:

```julia
julia> x = @SVector(rand(3)); y = @SVector(rand(3)); period = @SVector(rand(3));

julia> function getdx(x,y,period)
           delta = x - y
           ifelse.(delta .> 0.5 .* period ? delta - period : delta) .* sign.(x-y)
       end
getdx (generic function with 1 method)

julia> getdx(x,y,period)
ERROR: TypeError: non-boolean (SVector{3, Bool}) used in boolean context

```

I can’t find the possible combination of dots and not-dots or `@.` that makes this work as a one-liner.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 14, 2021, 6:51pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/8 "2021-06-14T18:51:55Z")

</div>

Change your `?` and `:` to commas.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2021, 6:54pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/9 "2021-06-14T18:54:35Z")

</div>

> [@mbauman](#):
>
> Maaaaaybe. It’s a little stranger than `.&&` and `.||`. It (currently) is syntacticly identical to the `if` statement, and we don’t support `if.` or `.if` . Are `a .? b : c` and `a ? b .: c` errors?

`a && b` was syntactically identical to

```julia
if a; b end

```

and

```julia
if !(a); b end

```

and nobody was arguing in that pr that it meant that we had to add support for `if.`

That said, yeah expressions like `a .? b .: c` are pretty ugly

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 14, 2021, 6:57pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/10 "2021-06-14T18:57:47Z")

</div>

> [@mbauman](#):
>
> Change your `?` and `:` to commas.

😳 😳 😳

oh, sorry, I think changed from one to the other syntax so many times that I got lost

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2021, 7:10pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/11 "2021-06-14T19:10:18Z")

</div>

If you want a macro that does this for you, you could always just do something like

```julia
julia> using MLStyle

julia> macro (..)(ex)
           f = @λ begin
               :($a ? $b : $c) => :($Base.ifelse($(f(a)), $(f(b)), $(f(c))))
               x => x
           end
           esc(:($Base.@. $(f(ex))))
       end
@.. (macro with 1 method)

julia> let x = rand(3), y = rand(3);
           @.. (x-y > 0.5 ? x : y )
       end
3-element Vector{Float64}:
 0.18240422481232943
 0.8391572489988877
 0.43624514306257667

```

This works correctly on nested expressions:

```julia
julia> let x = rand(3), y = rand(3);
           @.. (x-y > 0.5 ? (x > y ? y : x) : y)
       end
3-element Vector{Float64}:
 0.7793973727797479
 0.3033699172383637
 0.625107294185069

```

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [June 14, 2021, 7:27pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/12 "2021-06-14T19:27:59Z")

</div>

But won’t this macro always evaluate both branches?

You can write something like this:

```julia
broadcast(xs,ys) do x,y
    x-y>0.5 ? x : y
end

```

where in reality, surely the expressions will be a bit longer: If you don’t want `ifelse`, there must be some work you’d like not to happen when the condition is not met, so it can’t just be one symbol.

You can also write `g(x,y) = @cast _[i] := x[i]-y[i] > 0.5 ? x[i] : y[i]` using TensorCast, after someone complained that it didn’t work…

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 14, 2021, 7:35pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/13 "2021-06-14T19:35:29Z")

</div>

> [@Mason](#):
>
> `a && b` was syntactically identical to

It’s superficial, but they were and are syntactically different:

```julia
julia> Meta.show_sexpr(:(a && b))
(:&&, :a, :b)
julia> Meta.show_sexpr(:(if a; b; end))
(:if, :a, (:block,
    :(#= REPL[7]:1 =#),
    :b
  ))

```

Whereas `a ? b : c` parses directly to an `:if` head. Like I said, just little things all around that can change, but the above is what I was referencing. The fact that `a && b` has its own special parsed form made it significantly easier to achieve `a .&& b`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2021, 7:39pm UTC](https://discourse.julialang.org/t/x-y-x-y-broadcasting-does-not-work/62903/14 "2021-06-14T19:39:18Z")

</div>

Aha, I see what you mean now. Thanks!
