简体   繁体   English

存在非短路逻辑运算符的原因

[英]Reason for the existence of non-short-circuit logical operators

When used with boolean operands, & and | boolean操作数一起使用时, &| become logical operators per Section 15.22.2 of the JLS . 根据JLS第15.22.2节成为逻辑运算符。 Unlike && and || &&||不同 , however, these don't short-circuit; 但是,这些不会短路; they always evaluate both sides. 他们总是评估双方。 I have a silly question: Why are the less-efficient non-short-circuit logical operators ( & , | ) still there, when we have the more-efficient short-circuit logical operators ( && , || )? 我有一个愚蠢的问题:当我们拥有更高效的短路逻辑运算符( &&|| )时,为什么效率较低的非短路逻辑运算符( &| )仍然存在? I mean, what is the real usage of the non-short-circuit logical operators, as opposed to with the short-circuit logical operators? 我的意思是,与短路逻辑运算符相比,非短路逻辑运算符的实际用途是什么? In other words, what is the usage of always evaluating both sides by using the non-short-circuit logical operators? 换句话说,总是通过使用非短路逻辑运算符来评估双方的用法是什么?

Updated answer : 更新的答案

Apologies, I missed the word "logical" in your question even though it is there. 道歉,我在你的问题中错过了“逻辑”这个词,即使它 存在。 (I've taken the liberty of emphasizing it a bit with an edit.) (我冒昧地用编辑来强调它。)

Consider the case where you want any side-effects to always occur, regardless of whether the left-hand expression evaluates true or false . 考虑您希望始终发生任何副作用的情况,无论左侧表达式是评估true还是false Eg, contrast: 对比:

if (foo() & bar()) {
    // Only call this if both operations returned true
}

with

if (foo() && bar()) {
    // Only call this if both operations returned true
}

Let's assume both foo and bar have effects that we want to have happen regardless of whether foo returns true or false . 让我们假设foobar都有我们想要发生的效果,无论foo返回true还是false In the first one above, I know that bar will always get called and have its effect. 在上面的第一个中,我知道 bar总会被调用并产生效果。 In the latter, of course, bar may or may not get called. 当然,在后者中, bar可能会也可能不会被调用。 If we didn't have the non-short-circuit version, we'd have to use temporary variables: 如果我们没有非短路版本,我们必须使用临时变量:

boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
    // ...
}

You might argue (I probably would) that you should do that anyway , because it's way too easy to misread if (foo() & bar()) , but there we go, a pragmatic reason for having non-short-circuit versions. 你也许会说(我可能会),你应该做的是, 无论如何 ,因为它太容易误读if (foo() & bar())但我们去,对于具有非短路版本务实的原因。

Original answer : 原始答案

How would you propose & (or | ) be a short-circuited operator? 您如何建议& (或| )成为短路运营商? With && and || 使用&&|| , it makes sense because you're dealing with boolean conditions: They can be true or false, there are no shades of grey. ,这是有道理的,因为你正在处理布尔条件:它们可以是真或假,没有灰色阴影。 But & and | 但是&| deal with bits, not booleans. 处理比特,而不是布尔。 The result is a number. 结果是一个数字。 I mean, I guess & could not evaluate the right-hand side if the left-hand side were 0 , and similarly | 我的意思是,我想&若左侧是无法评估右侧0 ,同样| could not evaluate it if the left-hand side were all-bits-on for whatever the type was, but I don't see much point to making the one edge case of each operator significant (as compared to the 254 or more other cases). 对于任何类型的左侧,如果左侧都是全部位,则无法评估它,但我没有看到使每个运算符的一个边缘情况显着(与254或更多其他情况相比) )。

There are instances where the components of a boolean expression involve operations that you'd want to have executed in all cases. 在某些情况下,布尔表达式的组件涉及您希望在所有情况下执行的操作。 Consider the following example of checking a password for validity: 请考虑以下检查密码有效性的示例:

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-prompt

}

If the second condition was not evaluated due to short-circuiting, attempts would never be incremented. 如果由于短路而没有评估第二个条件,则attempts永远不会增加。 Thus greater programmer flexibility is enabled. 因此,启用了更高的程序员灵活性。

My case (C++): 我的情况(C ++):

void setFields(Parameters bundle)
{
  if (setIfDifferent(&field1, bundle.value1) | 
      setIfDifferent(&field2, bundle.value2) |
      setIfDifferent(&field3, bundle.value3)) {
    storeState();
  }
}

setIfDifferent() sets the object's field with new value if they differ, in which case it returns true; setIfDifferent()如果对象的字段不同则设置新值,在这种情况下它返回true; or it returns false in case the field's and the new value are the same. 或者在字段和新值相同的情况下返回false。 So, we want to try to set all fields, and if any of them changed, then we want to store new object's state. 因此,我们想尝试设置所有字段,如果其中任何字段发生了变化,那么我们希望存储新对象的状态。

You can have some side-effects in logical expression, for example you can assign simultaneously with checking. 您可以在逻辑表达式中有一些副作用,例如,您可以同时分配检查。 This may work wrongly if only one part evaluated. 如果仅评估一个部件,这可能会错误地工作。

Can't remember good example now, but remember that I was in need of "non-short-circuit" operators sometimes. 现在不记得好的例子,但请记住,我有时需要“非短路”操作员。

Hmmm.... Below is WRONG example, which won't work without "non-short-circuit" OR: 嗯....以下是错误的例子,如果没有“非短路”OR,它将无法工作:

if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {

    // do something which requires bot object1 and object2 assigned

}

In my case, I have two methods that compare two different but related objects (Object2 is an attribute of Object1) to see if there were any changes. 在我的例子中,我有两个方法比较两个不同但相关的对象(Object2是Object1的一个属性),看看是否有任何变化。 An update needs to happen if either are updated, but both need to be evaluated so that the objects will be modified if both have been changed. 如果更新了任何更新,则需要进行更新,但需要对两者进行评估,以便在两者都已更改的情况下修改对象。 Therefore, a single pipe "OR" comparison is required. 因此,需要单个管道“OR”比较。

EX: EX:

if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
    updateObject1(object1);
}

Technically, & and | 从技术上讲,&和| are not logical, they're bitwise operators that become logical operators when associated with booleans. 它们不是逻辑的,它们是按位运算符,在与布尔值相关时成为逻辑运算符。

There are times when you'd want to include assignment expressions inside your logical expressions. 有时您希望在逻辑表达式中包含赋值表达式。

Say: 说:

if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
 //now do something here with a and b that has been cached
}

If I had used ||, I'd not be able to perform the above check and would have had to split the assignments into separate statements. 如果我使用了||,我将无法执行上述检查,并且必须将分配拆分为单独的语句。 I've never come across scenarios like this during application development, but come across it a few times while writing algorithms. 我在应用程序开发过程中从未遇到过这样的场景,但在编写算法时遇到过这种情况。

Of course, you could use unary operators on the logical expressions or pass variables by reference into a predicate, but those seem like less common cases than the above. 当然,您可以在逻辑表达式上使用一元运算符或通过引用将变量传递给谓词,但这些似乎不像上面那样常见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM