# Apparent contradiction between Julia's short-circuiting rules and Julia's precedence rules

**URL:** https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408
**Category:** Internals & Design
**Created:** [November 11, 2018, 7:05pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408 "2018-11-11T19:05:55Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![larry](https://avatars.discourse-cdn.com/v4/letter/l/47e85d/32.png) [@larry](https://discourse.julialang.org/u/larry)
#### Post date: [November 11, 2018, 7:05pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/1 "2018-11-11T19:05:55Z")

</div>

I’ve found myself unable to explain the output of the following simple Julia program. It appears the output is totally dependent on whether one applies the short-circuiting rules or the precedence rules first. Short-circuiting is a minor optimization for a couple of operators whereas precedence affects all operators. Yet Julia seems to treat short-circuiting as the more important of the two. An example:

```julia
# Apparent conflict between precedence and short-circuit evaluation
# First define some helper functions
t(x)=(println(x);true)
f(x)=(println(x);false)
# Now comes the critcal expression
t(1) || f(2) && f(3)
# If one starts with the short-circuit rules, one would argue that || doesn't
# need to evaluate f(2) && f(3), because t(1) is true, giving an output
# of 1 \n true. By actual experiment this is what Julia does.
# However, one could start with the precedence rules. && has higher precedence,
# so it is evaluated first. The fact that || doesn't need the result of && is
# irrelevant because we aren't evaluating ||. f(2) ie evaluated and then by
# the short-circuiting of &&, f(3) is ignored. So 2 \n is outputted and
# false is returned. || now is the only remaining operator, so t(1) is
# evaluated, causing the output now to be 2 \n 1 \n and returning true. Now
# the short-circuit rules claim we should ignore the value of && and return true
# as the final value.
# Julia apparently applies short-circuit before precedence. Why??

```

---

<div class="post-metadata">

### Author: ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)
#### Post date: [November 11, 2018, 7:23pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/2 "2018-11-11T19:23:46Z")

</div>

Short-circuiting is _not_ an optimization. It’s part of the semantics of `||` and `&&`.  
It also doesn’t contradict precedence. `a || b && c` is interpreted as `a || (b && c)` according to precedence rules, but according to short-circuit rules `(b && c)` is evaluated only if `a` evaluates to `false`.  
This is the same behavior as in many other languages, including C, Java and Python.

---

<div class="post-metadata">

### Author: ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)
#### Post date: [November 11, 2018, 7:42pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/3 "2018-11-11T19:42:48Z")

</div>

You should wrap in code blocks to avoid “shouting”

---

<div class="post-metadata">

### Author: ![larry](https://avatars.discourse-cdn.com/v4/letter/l/47e85d/32.png) [@larry](https://discourse.julialang.org/u/larry)
#### Post date: [November 11, 2018, 10:19pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/4 "2018-11-11T22:19:44Z")

</div>

Thank you to Michael and “yha” for their prompt replies.

First Michael: Sorry but this is the first time in several years I have used a list which needed to wrap code blocks. I’ll try not to shout again! My apologies.

Next yha: I have to respectfully disagree with some of your comments. The point I was trying to make with the comment about optimization is that short-circuiting is used because of the peculiarities of two specific operators. Technically you are correct in saying that short-circuiting is part of their semantics, but nobody would even care if short-circuiting didn’t optimize their run-time behavior.

I have to disagree with your statement that “It (short-circuiting) also doesn’t contradict precedence”. Your following sentence starts to indicate why, but you need to notice that the operands you call a, b, and c actually have side-effects (doing output). If precedence rules are followed, the evaluation of the “and” operator causes some output to occur. By the time you are checking the semantics (or anything else) about the “or” operator, the output may have already reached a physical device and hence CANNOT be ignored no matter what the semantics of the “or” operator are. The output is different depending on whether you pay attention first to precedence or short-circuiting.

The last sentence may be the real answer here. There are plenty of examples of ideas put into programming languages for no better reason than compatibility with older languages. For my personal purposes, I’m just going to continue to do what I’ve always done: don’t use short-circuit operators if there is any chance of side effects.

Again, thanks to both of you.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [November 11, 2018, 10:29pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/5 "2018-11-11T22:29:31Z")

</div>

These are the relevant facts:

- `&&` and `||` are both left associative.
- `&&` has higher precedence than `||`.
- `&&` only evaluates the right expression if the left expression is true.
- `||` only evaluates the right expression if the left expression is false.

The first fact is not actually relevant in this particular case but would be in longer chains. In this expression:

```julia
t(1) || f(2) && f(3)

```

Precedence implies that it’s this:

```julia
t(1) || (f(2) && f(3))

```

Since `t(1)` evaluates to true, `f(2) && f(3)` is not evaluated.

---

<div class="post-metadata">

### Author: ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)
#### Post date: [November 11, 2018, 10:34pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/6 "2018-11-11T22:34:12Z")

</div>

> [@larry](#):
>
> nobody would even care if short-circuiting didn’t optimize their run-time behavior.

Actually, most everybody would care because it would break a lot of code. These are common idiom in Julia:

```julia
is_ok(arguments) || error("invalid arguments)
x < 0 && break

```

etc.  
It’s also common, both in Julia and other language to do things like ` if x != 0 && a_condition(a/x)` or `if x in collection && collection[x] == something`  
which relies on short-circuiting to avoid an error on the second operand.

> [@larry](#):
>
> By the time you are checking the semantics (or anything else) about the “or” operator, the output may have already reached a physical device

No, it may not. I think you misunderstand what operator precedence means. It _does not_ mean that in `a || b && c`, the expression `b && c` is evaluated first. It only means that it is evaluated as `a || (b && c)` rather than `(a || b) && c`. And the evaluation of `a || (b && c)` does not result in evaluation of `(b && c)` if `a` is `true`.

---

<div class="post-metadata">

### Author: ![larry](https://avatars.discourse-cdn.com/v4/letter/l/47e85d/32.png) [@larry](https://discourse.julialang.org/u/larry)
#### Post date: [November 12, 2018, 2:59pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/7 "2018-11-12T14:59:57Z")

</div>

Again, thank you for all who contributed! I think it is time to refocus on what the original question was. I understand that Julia does short-circuit evaluation on expressions involving the “and” and “or” operators because I actually ran the example I gave through Julia. I understand what short-circuiting does. As you may have guessed, I regard it as a bad idea but I don’t question that Julia use it.

My question is why the precedence rule stating that “and” has higher precedence than “or” isn’t applied before short-circuiting, contrary to what Julia does. Several responders seem to think that merely means inserting parentheses before short-circuiting, so let me suggest a simple and well-known experiment to show what I actually meant:

1. Convert the expression in my example to postfix (prefix works too but for the sake of definiteness allow me to use postfix). The usual stack-based algorithm depends ONLY on the precedence of the operators but not on any short-circuiting, so you will get a clear indication of what happens when precedence is done first. The postfix conversion algorithm is a common method of understanding expressions in a way that is precedence and parenthesis-free, so this is a reasonable way to proceed.

2. Now that all precedence has been eliminated we have completed the precedence-first part of my suggestion. Short-circuiting can easily be done on the resulting expression by an obvious algorithm.

If you try this you will get a different answer than Julia, yha, and Stefan get and IMHO it is the correct answer for doing the parsing “precedence-first”.

Hopefully in conclusion, I think yha’s answer that Julia’s developers wanted to maintain the same method of parsing expressions involving short-circuit operators as C, Python, and Java use is probably the best answer I’m going to get. I’ll just remember not to use terms with side effects in them. Again, thanks to everyone.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [November 12, 2018, 3:58pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/8 "2018-11-12T15:58:37Z")

</div>

> [@larry](#):
>
> Several responders seem to think that merely means inserting parentheses before short-circuiting

As far as I understand, this is _exactly_ what it means. Can you provide any source that says differently?

Or which programming languages behave differently?

---

<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: [November 12, 2018, 4:20pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/9 "2018-11-12T16:20:52Z")

</div>

Please show some consideration to the users taking the time to read and discuss your post by formatting it properly. You can still edit it. The site uses [CommonMark](https://commonmark.org/help/).

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [November 12, 2018, 4:51pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/10 "2018-11-12T16:51:49Z")

</div>

> [@DNF](#):
>
> As far as I understand, this is _exactly_ what it means.

It is. The whole postfix argument doesn’t make much sense to me and seems to lead to an incorrect conclusion, so appears to be unhelpful on the whole.

> Or which programming languages behave differently?

As far as I’m aware they all work like this although some give `&&` and `||` the same precedence which leads to left-to-right evaluation.

---

<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: [November 12, 2018, 5:11pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/11 "2018-11-12T17:11:29Z")

</div>

There’s a reason why `&&` and `||` appear in the [Control flow chapter](https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation-1) of the documentation — they’re not normal operators. They’re syntax. Unlike many other operators, you cannot use them as first-class functions. They cannot be extended with multiple dispatch. And perhaps most importantly, you cannot reference them independently or in prefix function call syntax, so your thought experiment doesn’t work in Julia.

If you want logical operators that don’t short circuit, you can use the bitwise `&` and `|`, but be aware that their precedences are tuned for bitwise arithmetic.

See also the difference between the ternary operator `? :` and the `ifelse` function.

---

<div class="post-metadata">

### Author: ![Non-Contradiction](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-contradiction/32/2208_2.png) [@Non-Contradiction](https://discourse.julialang.org/u/Non-Contradiction)
#### Post date: [November 12, 2018, 5:20pm UTC](https://discourse.julialang.org/t/apparent-contradiction-between-julias-short-circuiting-rules-and-julias-precedence-rules/17408/12 "2018-11-12T17:20:51Z")

</div>

The problem seems to be more with the understanding of precedence than with the short-circuiting rule.  
Here is an example only about precedence:

```julia
julia> (println("hello"); 1) + (println("world"); 2) * (println("!"); 3)
hello
world
!
7

```

and in R

```julia
> {print("hello"); 1} + {print("world"); 2} * {print("!"); 3}
[1] "hello"
[1] "world"
[1] "!"
[1] 7

```

and in Python:

```julia
>>> def a(s, i):
... print(s)
... return(i)
... 
>>> a("hello", 1) + a("world", 2) * a("!", 3)
hello
world
!
7

```

So all the languages here know the precedence of `*` is higher than `+`, but they don’t evaluate `(println("world"); 2) * (println("!"); 3)` first, and the precedence really means inserting parentheses.
