# Unexpected result from short-circuiting (inline if)

**URL:** <https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400>\
**Category:** General Usage\
**Created:** [February 10, 2023, 8:57am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400 "2023-02-10T08:57:08Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![CarlosST](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlosst/32/46770_2.png) [@CarlosST](https://discourse.julialang.org/u/CarlosST)\
**Post date:** [February 10, 2023, 8:57am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/1 "2023-02-10T08:57:08Z")

</div>

I’m quite familiar with using short-circuit evaluation as an inline if, and my understanding was that writing `cond && (expression)` is exactly identical to the more traditional:

```julia
if cond
    expression;
end

```

However, I found a case where this leads to unexpected behavior. I needed to find the minimum and maximum of each sub-list of a list of lists `T`, element-wise (among other things). So I wrote something in the same spirit of the following:

```julia
T = [[1,2],[0,1],[1,-1]];
limits = [Inf,-Inf,Inf,-Inf];
cond = true;

for t in T
  for i in eachindex(t)
    if cond
      limits[2*i-1:2*i] .= min(limits[2*i-1],t[i]), max(limits[2*i],t[i]);
    end
  end
end

```

Here the behavior is as expected, with `limits = [0.0,1.0,-1.0,2.0]`. However, if I substitute the if in the middle with:

```julia
cond && ( limits[2*i-1:2*i] .= min(limits[2*i-1],t[i]), max(limits[2*i],t[i]) )

```

I obtain `limits = [0.0,0.0,-1.0,-1.0]`!

Why is this the case? By trial-and-error, I found that putting additional parentheses around `min` and `max` fixes the issues, but this unexpected result makes me wary of using short-circuit evaluation so freely. Does anybody have any idea?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [February 10, 2023, 9:14am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/2 "2023-02-10T09:14:32Z")

</div>

> [@CarlosST](#):
>
> Why is this the case?

It’s due to a difference in parsing (I removed the indexing for clarity):

```julia
julia> Meta.@lower if cond
             limits .= min(limits,t), max(limits,t);
           end
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ goto #3 if not cond
    @ REPL[2]:2 within `top-level scope`
2 ─ %2 = limits
│ %3 = min(limits, t)
│ %4 = max(limits, t)
│ %5 = Core.tuple(%3, %4)
│ %6 = Base.broadcasted(Base.identity, %5)
│ %7 = Base.materialize!(%2, %6)
└── return %7
3 ─ return nothing
))))

julia> Meta.@lower cond && (limits .= min(limits,t), max(limits,t))
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ goto #3 if not cond
2 ─ %2 = limits
│ %3 = min(limits, t)
│ %4 = Base.broadcasted(Base.identity, %3)
│ %5 = Base.materialize!(%2, %4)
│ %6 = max(limits, t)
│ %7 = Core.tuple(%5, %6)
└── return %7
3 ─ return false
))))

```

Note that in the first case, the tuple is destructured & then broadcast, while in the latter case only the first element of the tuple is broadcast. I.e., the latter case constructs the outer tuple due to your parentheses making the whole expression after the `&&` a tuple, and not just the part after the broadcasted assignment.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 10, 2023, 9:18am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/3 "2023-02-10T09:18:32Z")

</div>

This looks like a nice one to add to [Syntax Surprises](https://discourse.julialang.org/t/syntax-surprises/92369).

Observe:

```julia
julia> a = 1, 2
(1, 2)

julia> a = (1, 2)
(1, 2)

julia> (a = (1, 2))
(1, 2)

julia> (a = 1, 2)
ERROR: syntax: invalid named tuple element "2" around REPL[228]:1

```

The basic idea is: in most circumstances, you should expect to have to wrap `Tuple`s in parentheses; excluding the parentheses for standalone assignment statements is the _exception_, not the rule.

Within parentheses, `=` binds more tightly than comma—this allows `NamedTuple`s to be formed. Namely, we get to make these:

```julia
julia> (a=1, b=2)
(a = 1, b = 2)

```

But, it comes with the drawback of somewhat unintuitive parsing rules, where the binding tightness of `=` depends on whether it’s wrapped in parentheses or not.

To illustrate how this influences your case:

```julia
julia> b = [0, 0];

julia> if true; b .= (1, 2) end; b
2-element Vector{Int64}:
 1
 2

julia> true && (b .= 1, 2)
([1, 1], 2)

julia> b
2-element Vector{Int64}:
 1
 1

julia> true && (b .= (1, 2)); b
2-element Vector{Int64}:
 1
 2

```

---

<div class="post-metadata">

**Author:** ![CarlosST](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlosst/32/46770_2.png) [@CarlosST](https://discourse.julialang.org/u/CarlosST)\
**Post date:** [February 10, 2023, 9:45am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/4 "2023-02-10T09:45:16Z")

</div>

Thank you (and @Sukera ) so much! You both made it absolutely clear to why this is the case, and I chose your answer as solution mainly for its accessibility. I love Julia’s flexibility, but sometimes I do feel like I’m allowed to do too much!

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 10, 2023, 9:54am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/5 "2023-02-10T09:54:39Z")

</div>

Thanks! Honestly though, I feel like this one’s a bug so I [filed an issue](https://github.com/JuliaLang/julia/issues/48627). There’s good reason to disallow `(a = 1, 2)`, because `NamedTuple`s are awesome, but then `(b .= 1, 2)` should be disallowed too.

It doesn’t help that broadcasting automagically fills dimensions, so it causes a silent error.

---

<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:** [February 10, 2023, 10:03am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/6 "2023-02-10T10:03:11Z")

</div>

> [@uniment](#):
>
> It doesn’t help that broadcasting automagically fills dimensions, so it causes a silent error.

Indeed, that’s the worst part in this example

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [February 10, 2023, 4:18pm UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/7 "2023-02-10T16:18:43Z")

</div>

> [@uniment](#):
>
> but then `(b .= 1, 2)` should be disallowed too.

`=` has special rules for parsing within parentheses. `.=` is not `=` and similarity in this context is superficial. `b .= 1` is a complete and legal expression.

That said, I had expected the following to be legal:

```julia-repl
julia> ((a = 1), 2)
ERROR: syntax: invalid named tuple element "2" around REPL[405]:1

```

I’d expected that the expression would evaluate to `(1,2)` and that afterward I would have `a` bound to `1`. Not that it would tunnel through the parentheses and try to build a `NamedTuple`.

Even more strangely, the outer parentheses were apparently irrelevant to what I had tried:

```julia-repl
julia> (a = 1), 2
ERROR: syntax: invalid named tuple element "2" around REPL[406]:1

julia> (a = 1), (b = 2)
(a = 1, b = 2)

```

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 10, 2023, 7:57pm UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/8 "2023-02-10T19:57:37Z")

</div>

> [@mikmoore](#):
>
> `.=` is not `=` and similarity in this context is superficial.

In that case, `(b .= 1, 2)` should parse the same as `b .= 1, 2` to mean `b .= (1, 2)` instead of `(b .= 1), 2`.

> [@mikmoore](#):
>
> the following

![image](https://global.discourse-cdn.com/julialang/original/3X/0/5/05f6ba6efecf19f13213dd072053fb722b78d141.jpeg)

cc @c42f

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 12, 2023, 9:03am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/9 "2023-02-12T09:03:03Z")

</div>

> [@mikmoore](#):
>
> Not that it would tunnel through the parentheses and try to build a `NamedTuple`

Yes this is a syntax peculiarity and I don’t like it either (basically the same issue as described here [Syntax Surprises - #35 by c42f](https://discourse.julialang.org/t/syntax-surprises/92369/35))

> [@mikmoore](#):
>
> ```julia
> julia> (a = 1), (b = 2)
> (a = 1, b = 2)
> 
> ```

Yikes this one is a definite syntax bug, we should not be allowing this!

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 13, 2023, 5:01am UTC](https://discourse.julialang.org/t/unexpected-result-from-short-circuiting-inline-if/94400/10 "2023-02-13T05:01:09Z")

</div>

> [@c42f](#):
>
> Yikes this one is a definite syntax bug, we should not be allowing this!

I started a label to track syntax WATs in JuliaSyntax.jl and added an issue for this.

> **[Issues · JuliaLang/JuliaSyntax.jl](https://github.com/JuliaLang/JuliaSyntax.jl/labels/syntax%20WAT)**
>
> A Julia frontend, written in Julia. Contribute to JuliaLang/JuliaSyntax.jl development by creating an account on GitHub.
