&&= 和 ||= 运算符

发布于 2024-09-28 11:40:41 字数 858 浏览 3 评论 0原文

可能的重复:
为什么 Java 没有条件与和条件或运算符的复合赋值版本? (&&=,||=)
为什么“&&=”运算符不存在?

今天在工作中,我写了下面的 LOC(b 和 b1 的真实身份是保密的:)

b &&= b1; // meaning b = b && b1; 

我盯着它看了几秒钟,意识到不存在这样的运算符。可以肯定的是,我单击了“编译”,但它失败了。为了确保万无一失,我查阅了标准。

没有这样的运营商有什么具体原因吗?我能想到一些:

  1. b &&= b1b = b &&由于 && 的短路评估,b1 可能不等效。
  2. &&= 很丑陋
  3. &&= 很少需要

我并不认为拥有这样的运算符会非常有用,不。我也不认为上述三个原因中的任何一个或全部都不足以阻止创建该运算符。我的问题如下:是否有我正在监督的更严重的原因?

Possible Duplicates:
Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)
Why does a “&&=” Operator not exist?

Today at work I wrote the following LOC (the real identities of b and b1 are confidential :)

b &&= b1; // meaning b = b && b1; 

I stared at it for a couple of seconds and realized that there exists no such operator. Just to be sure, I clicked on compile and it failed. To be dead sure I consulted the standard.

Are there specific reasons that there are no such operators? I can think of some:

  1. b &&= b1 and b = b && b1 may not be equivalent because of short-circuit evaluation of &&.
  2. &&= is ugly
  3. &&= is rarely needed

I do not claim that it would be very useful to have such operators, no. I also don't claim that any or all of the three above reasons are not enough to refrain from creating that operator. My question is the following: is there maybe a much more serious reason which I am overseeing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

自在安然 2024-10-05 11:40:41

我不知道为什么问题和一些答案都提到相应逻辑运算符的短路行为是一个潜在问题。

定义 &&=||= 运算符绝对不存在与短路相关的问题。它们应该用+=和其他类似的运算符统一定义,这意味着a &&= b应该等同于a = a && b,但 a&&= 版本中仅计算一次。这意味着如果 a 最初为零,则根本不会计算 b。简单的。

因此,它们在语言中不存在的唯一原因是“只是因为”。

I don't know why both the question and some of the answers mention short-circuiting behavior of the corresponding logical operators as a potential issue.

There's absolutely no short-circuit-related problems with defining &&= and ||= operators. They should be defined uniformly with += and other similar operators, meaning that a &&= b should be equivalent to a = a && b, but with a being evaluated only once in &&= version. This means in turn that b is not evaluated at all if a is originally zero. Easy.

So, the only reason they don't exist in the language is, well, "just because".

独木成林 2024-10-05 11:40:41

我以前也想要它们。我怀疑丑陋本身就是决定因素,短路行为是我迄今为止听到的反对他们的最好论据。

另一个影响因素是 C 被设计为接近金属操作,几乎所有运算符都直接对应于主要体系结构中的指令。我认为 x86、PPC 等上没有直接实现 b &&= b1; 的指令

I've wanted them before as well. I doubt that ugliness was by itself the determining factor, the short-circuiting behavior is the best argument against them I've heard so far.

Another contributing factor is that C is designed to operate close to the metal, pretty much all of the operators correspond directly to an instruction in major architectures. I don't think there is an instruction on x86, PPC, etc that directly implements b &&= b1;

紫竹語嫣☆ 2024-10-05 11:40:41

运营商不存在的最大原因可能是 K&R 没有想到任何有吸引力的方式来定义它们。我有时也想要一个 ->= 运算符(ptr->=next 相当于 ptr = ptr->whatever)。

我认为 &&= 的一个问题是,以下哪一项最有用或者应该是哪一项并不明显:

  if (lhs && rhs) lhs = 1; else lhs = 0;
  if (!rhs) lhs = 0; else lhs = !(!lhs));
  if (lhs && !rhs) lhs = 0;
  if (!rhs) lhs = 0;

The first variation is the one most clearly suggested by the syntax, but from a practical standpoint, if neither term is zero, it would often be more useful to leave the left-hand side alone than to set it to "1".

顺便说一句,我经常希望有一个逗号运算符的变体,它可以评估左侧,保存值,然后评估右侧,并返回左侧的值。相当于:

int foo(int p1, int p2) return p1;

except applicable to any type (p2 need not be the same type as p1, and could be void), and with a guaranteed left-to-right evaluation order. Would be very handy for things like post-increment indexing with a non-unit step, e.g., arr[ptr ~, ptr+=2]; or for certain types of data-swap operations, e.g., var1 = (var2 ~, var2=var1); etc.

The biggest reason the operators don't exist is probably that K&R didn't think of any appealing way to define them. I've also sometimes wanted a ->= operator (ptr->=next would be equivalent to ptr = ptr->whatever).

A problem I think with &&= is that it's not obvious which of the following would be most useful, or which it's supposed to be:

  if (lhs && rhs) lhs = 1; else lhs = 0;
  if (!rhs) lhs = 0; else lhs = !(!lhs));
  if (lhs && !rhs) lhs = 0;
  if (!rhs) lhs = 0;

The first variation is the one most clearly suggested by the syntax, but from a practical standpoint, if neither term is zero, it would often be more useful to leave the left-hand side alone than to set it to "1".

BTW, I've often wished for a variation of the comma operator which would evaluate the left side, save the value, then evaluate the right side, and return the value of the left side. Equivalent to:

int foo(int p1, int p2) return p1;

except applicable to any type (p2 need not be the same type as p1, and could be void), and with a guaranteed left-to-right evaluation order. Would be very handy for things like post-increment indexing with a non-unit step, e.g., arr[ptr ~, ptr+=2]; or for certain types of data-swap operations, e.g., var1 = (var2 ~, var2=var1); etc.

独自←快乐 2024-10-05 11:40:41

因为 a && 的结果是b 始终是 01,我认为只有 C99 _Bool 类型对此的解释才是明确的。由于创建 C 时不存在该运算符,因此不包括该运算符。现在没有人轻易地向 C 添加另一个运算符,因为这会对所有现有的解析器产生影响。

Because the result of a && b is always 0 or 1, I think the interpretation of this would only be unambiguous for the C99 _Bool type. Since this didn't exist at the time C was created, this operator was then not included. And nowadays nobody easily adds another operator to C, since this would have an impact on all existing parsers.

谁的新欢旧爱 2024-10-05 11:40:41

就我个人而言,我会投票支持你所支持的第一个理由。布尔运算符具有短路语义,如果转换为赋值运算符,将会导致一些非常棘手的情况。要么你不再让它们短路,要么你创建了一些奇怪的“可选”赋值运算符(执行右侧的操作并仅当 LHS 上的值已经非零时才在结果中赋值)。无论哪种方式,你都会产生微妙的错误,因为人们会期待其他行为。

Personally I'd vote for the first rationale you went with. The boolean operators have short-circuit semantics, which would make for some really gnarly situations if translated into asignment operators. Either you don't make them short-circuit anymore, or you created some weird "optional" assignment operator (do the stuff on the right and assign in the result only if the value on the LHS is already non-zero). Either way you'd create subtle bugs because people would be expecting the other behavior.

那些过往 2024-10-05 11:40:41

编辑:错误的语言,但仍然适用

我同意你的三个原因,尽管在一种情况下,在编写自定义反序列化例程时,我对缺少此运算符感到遗憾。在一些情况下,不正确序列化的对象并不是真正的“异常”(并且为了防止 C# 中非常常见的失败的异常开销),我将使用布尔返回值来表示反序列化操作是否成功。

这段代码完全是理论性的,Nested1、Nested2 和 Nested3 都是结构体:

public struct ComplexStruct
{
    private Nested1 nested1;
    private Nested2 nested2;
    private Nested3[] nested3;

    public bool Read(Reader reader)
    {
       bool ret = true;
       int nested3Length = 0;

       ret &&= nested1.Read(reader);
       ret &&= nested2.Read(reader);
       ret &&= reader.ReadInt32(ref nested3Length);

       for(int i = 0; (ret && i < nested3Length); i++)
       {
          ret &&= nested3[i].Read(reader);
       }

       return ret;
    }
}

EDIT: Wrong language, but still applies

I agree with your three reasons, although there is one scenario where I have lamented the lack of this operator, when writing custom deserialization routines. In a couple of cases where an improperly serialized object wasn't really "exceptional" (and to prevent exception overhead in C# for very common failures), I would use boolean return values to signify whether a deserialization operation was successfull.

This code is completely theoretical, and Nested1, Nested2 and Nested3 are all structs:

public struct ComplexStruct
{
    private Nested1 nested1;
    private Nested2 nested2;
    private Nested3[] nested3;

    public bool Read(Reader reader)
    {
       bool ret = true;
       int nested3Length = 0;

       ret &&= nested1.Read(reader);
       ret &&= nested2.Read(reader);
       ret &&= reader.ReadInt32(ref nested3Length);

       for(int i = 0; (ret && i < nested3Length); i++)
       {
          ret &&= nested3[i].Read(reader);
       }

       return ret;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文