Scala中的三元运算符

New*_*bie 1 if-statement scala ternary-operator

我想简化这个:

var countA: Int = 0
var countB: Int = 0

if (validItem) {
  if (region.equalsIgnoreCase( "US" )) {
    if (itemList > 0) {
      countB = 1
    } else {
      countA = 1
    }
  } else {
    countB = 1
  }
} else {
  countA = 1
}
Run Code Online (Sandbox Code Playgroud)

如何在scala中使用三元运算符.

lau*_*lic 10

我认为简短的答案是 Scala 中没有三元 ?:运算符。尽管您可以使用隐式来模仿语法(请参阅@jwvh的答案),但我认为它并没有真正简化任何事情。

传统的方法有几个重要的特性?:

  1. 它总是有两个分支
  2. 根据上一个属性,三元运算符始终返回一个值(这主要是使用 的要点?:

    val result: Int = if (true) 1 else 2
    // result is 1
    
    Run Code Online (Sandbox Code Playgroud)
  3. 分支被延迟评估

    if (true) 1 else (0/0) // returns 1
    if (false) 0/0 else 2  // returns 2
    // i.e. 0/0 is not evaluated
    
    Run Code Online (Sandbox Code Playgroud)

如您所见,在 Scala 中if-else(使用else)构造满足这些属性。情况并非如此if-else,因为它不返回值。

所以底线是Scala你不需要三元运算符,因为你可以只使用if-else.

更新

正如阿列克谢·罗曼诺夫在评论中提到的,if没有的声明else实际上也满足了第一个条件。当你写的时候

val result = if (true) 1
Run Code Online (Sandbox Code Playgroud)

它实际上意味着if (true) 1 else (), soresult将使用 typeAnyVal而不是Int,因为表达式的返回类型if是两个分支的最低公共界限(IntUnit本例中)。


0__*_*0__ 8

您不应该在Scala中使用三元运算符.if你可以说,在Scala中,表达式不是声明val x = if (b) 1 else 2.

var在您的示例中的用法也指向一个问题,因为当您使用if表达式时通常可以避免这种情况.

让我们尝试分解代码以避免var,即首先删除所有if非对应表达式的语句,else并始终提供两个值:

var countA: Int = ???
var countB: Int = ???

if (validItem) {
  if (region.equalsIgnoreCase("US")) {
    if (itemList > 0) {
      countA = 0
      countB = 1
    } else {
      countA = 1
      countB = 0
    }
  } else {
    countA = 0
    countB = 1
  }
} else {
  countA = 1
  countB = 0
}
Run Code Online (Sandbox Code Playgroud)

现在,我们可以定义条件其中之一countA,并countB是一个:

val isUS     = region.equalsIgnoreCase("US")
val hasItems = itemList > 0
val isA      = !validItem || (isUS && !hasItems)
val isB      = !isA
// or: val isB = validItem && (!isUS || hasItems)
Run Code Online (Sandbox Code Playgroud)

然后:

val countA   = if (isA) 1 else 0
val countB   = if (isB) 1 else 0
Run Code Online (Sandbox Code Playgroud)


jwv*_*wvh 6

对于“新手”来说,这可能有点令人困惑,但是您可以Boolean像这样将三元方法附加到类中。

implicit class Ternary[T](condition: Boolean) {
  def ??(a: => T, b: => T): T = if (condition) a else b
}
Run Code Online (Sandbox Code Playgroud)

用法:

(4 == 4)??("yes","no")         // res0: String = yes
("abc".length < 2).??(1,0)     // res1: Int = 0
List('c').isEmpty.??('X','+')  // res2: Char = +
Run Code Online (Sandbox Code Playgroud)

  • 这有助于定义_看起来像_三元运算符的东西,但我认为它并没有真正帮助简化OP示例中的代码。 (2认同)