Kotlin中的XOR运算符是特性还是Bug?

10

我是一名Java开发人员,有很多年的经验,最近在Kotlin中发现了一些非常惊奇的东西。在Java中,有一个很少使用的逻辑运算符^XOR,但有时它很有用。例如:你可以轻松地检查两个数字中仅有一个大于零。

使用 &&AND 运算符以及一些变量 ab,代码如下:

boolean valid = (a > 0 && b <= 0) || (a <= 0 && b > 0);

但可以轻松通过 ^ XOR 实现:

boolean valid = a > 0 ^ b > 0;

在 Kotlin 中,我们不使用 ^ 作为 XOR,而是使用 xor,同样的代码在 Kotlin 中看起来像这样:

val valid = a > 0 xor b > 0;

这里有一个问题,因为在Kotlin中,以下代码会导致编译错误!为什么?在Java中,所有逻辑运算符(&,&&,|,||,^)的优先级都低于关系运算符(>, >=, <, <=, ==, !=)。 在Koltin中也是一样的,但对于xor似乎不是这样。 所以它是这样的:

  1. a > 0会给出布尔值
  2. boolean xor b > 0首先评估为:boolean xor b而不是b > 0
  3. 最后我们得到了编译错误,提示:整数字面值不符合预期的类型布尔值

您可以在此处检查此情况:XOR not working well

有一个额外的情况:如果您认为这个方程式:a > 0 xor (b > 0)有效...好吧,没有。另一个编译错误:类型不匹配:推断类型为布尔类型,但预期为整型

有人能解释一下这种逻辑的目的是什么,还是它只是Kotlin语言中的一个错误?


2
我完全同意你的看法,这是一个漏洞,但无论是故意还是意外,这就是他们设计的方式。 - user207421
括号是你的朋友。 - NomadMaker
听起来像是语言设计上的缺陷。 - xinaiz
O.O 好发现!同意,这很奇怪。 - kmiklas
2个回答

16

xor 不是一个运算符,而是一个中缀函数。中缀函数调用优先级高于比较操作。 表达式

val valid = a > 0 xor b > 0 等同于 val valid = a > (0 xor b) > 0

  1. (0 xor b) 返回 Int 值
  2. a > (0 xor b) 返回 Boolean 值
  3. 它变成了 Boolean 和 Int 之间的比较 ((step 2 Boolean result) > 0),但你不能比较 Boolean 和 Int

修正后版本:

val valid = (a > 0) xor (b > 0)

我非常清楚这里的XOR是如何工作的 :) 问题在于,XOR是逻辑运算符,它应该比关系运算符具有更低的优先级,尤其是在Java中。问题不在于XOR如何工作,而在于为什么他们决定它以这种方式工作。 - Michał Kupisiński
1
为什么“它应该比关系运算符具有更低的优先级”?布尔代数中没有比较运算符。在Python中,异或(按位)的优先级也高于比较运算符。 - IR42
2
@DrawnRaccoon 因为它的方式与其他拥有此功能的编程语言不同。 - user207421
在我看来,没有理想的方法。XOR 可以是按位或逻辑的;按位版本比较运算符更应该具有更高的优先级,但逻辑版本的优先级应该更低——但在不同情况下具有不同优先级的操作符会让人感到困惑。因此,所有语言都在优先级上做出了妥协(或为两种情况使用不同的运算符)。但是,在 C 语言编写时,按位运算符的使用要少得多,所以 Kotlin 简单地将它们从语言中删除,并留给标准库处理——并根据其自己的优先级要求进行处理。 - gidds
1
xor 不是一个运算符,而是一个执行逻辑操作的函数:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/xor.html - gpunto
显示剩余2条评论

1

xor(作为中缀函数-文档)在Kotlin中的优先级低于算术运算符(*,/,%,+,-),高于比较运算符(<,>,<=,>=),相等性(==,!==)和赋值(=,+=,-=,*=,/=,%=)运算符。(有关完整的优先级参考,请查看此处。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接