Why does short circuit evaluation work when an operator priority says it should not?

In JavaScript and Java , the equality operator ( == or === ) takes precedence over the OR operator ( || ). However, both languages ​​( JS , Java ) support short circuiting in if :

When we have if(true || anything()) , anything() not evaluated.

You can also have the following expression: true || foo == getValue()) true || foo == getValue()) - for example, in an output expression, for example console.log(...); , or in assignment.

Now, according to the priority of the operator, a short circuit should not occur, as === = == > || in terms of priority. (In other words, a comparison must first occur, for which getValue() should be called, since equality checking takes precedence over OR comparisons). But it is so. getValue() not called (as you can easily verify by placing the output statement in its body).

Why (does a short circuit work when the priority of the operator says that it should not)?
Or am I confusing questions?

+5
source share
3 answers

Or am I confusing questions?

You. I think it’s much easier to think about priority as a grouping than about ordering. It affects the evaluation order, but only because it changes the grouping.

I definitely don't know about Javascript, but in Java operands are always evaluated in order from left to right. The fact that == has higher priority than || , means that

 true || foo == getValue() 

estimated as

 true || (foo == getValue()) 

but not

 (true || foo) == getValue() 

If you just think of priority in this way, and then think that evaluation is always left to right (therefore, the left operand || always evaluated to the right operand, for example), then everything is simple - and getValue() never evaluated due to a short circuit.

To eliminate a short circuit from an equation, consider this example instead:

 A + B * C 

... where A , B and C can be just variables or can be other expressions, such as method calls. In Java, this is guaranteed to be evaluated as:

  • Rate A (and remember it later)
  • Rate B
  • Rate C
  • Multiply the score of B and C
  • Add the result of the score A with the result of the multiplication

Note that although * has a higher priority than + , A is still rated to B or C If you want to think about priority in terms of ordering, pay attention to how multiplication still happens before adding, but it still does the evaluation order from left to right.

+15
source

According to the language specification https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24

At run time, the first expression of the first operand is evaluated; if the result is of type Boolean, it is subjected to unpacking the transformation (section 5.1.8).

If the resulting value is true, the value of the conditional expression or expression is true, and the expression of the right operand is not evaluated.

So, if you have a || b==c a || b==c , this is not interpreted as (a || b) == c , because || has a lower priority, as you found in the tutorial. Instead, it is interpreted as a || (b==c) a || (b==c) . Now, since a is the left side || is estimated first.

0
source

In this case, there is no operator priority. What you are asking is similar to the f(callback) statement, a callback function that is evaluated before f . It cannot be.

On the other hand, in JS || is one of the few places where you can watch laziness at a show. The == operator (as if it is an infix function, for example, in fully functional languages) takes two arguments, and the first on the left is evaluated first. If it allows true , the second argument is not even evaluated.

0
source

Source: https://habr.com/ru/post/1272249/


All Articles