有条件地调用成员函数而不使用临时var

And*_*lan 4 scala

我有一个表达式返回一个对象,我想只在某个布尔条件为真时才在结果对象上调用一个方法.我想在val中获得结果(无论是对象,还是在对象上调用方法的结果).

一种方法是使用临时var,例如在下面的示例中,其中List(3, 1, 2)是返回对象的(可能复杂的)表达式,list是临时var,并且.sorted是我想要有条件地调用的方法:

import scala.util.Random

val condition = Random.nextBoolean
val result = {      
  var list = List(3, 1, 2);
  if (condition) list = list.sorted
  list
}
Run Code Online (Sandbox Code Playgroud)

这样做的规范方法是什么,也许使用临时变量?

注意

if (condition) List(3, 1, 2).sorted else List(3, 1, 2)
Run Code Online (Sandbox Code Playgroud)

不太令人满意,因为List(3, 1, 2)通常可能是一个复杂的表达,我不想重复.

这是我发现的一种方法,不幸的是涉及给出显式类型(并且比引入上面的临时var更长,更复杂):

val condition = Random.nextBoolean
val result =
  (
    if (condition)
      {l: List[Int] => l.sorted}
    else
      identity(_: List[Int])
  ).apply(List(3, 1, 2))
Run Code Online (Sandbox Code Playgroud)

我怀疑必须有一种我没有认识到的更整洁的方式.

更新:一个稍微不那么丑陋的方法,遗憾的是仍然需要显式的类型信息:

val condition = Random.nextBoolean    
val result = {
    l: List[Int] => if (condition) l.sorted else l
  }.apply(List(3, 1, 2))
Run Code Online (Sandbox Code Playgroud)

kir*_*uku 9

您可以使用正向管道运算符:

implicit class PipedObject[A](value: A) {
  def |>[B](f: A => B): B = f(value)
}

scala> List(3, 1, 2) |> (xs => if (true) xs.sorted else xs)
res1: List[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)


Xav*_*hot 5

开始Scala 2.13,标准库现在提供链接操作pipe,可用于转换/管道具有感兴趣函数的值,从而避免中间变量:

import scala.util.chaining._

List(3, 1, 2).pipe(list => if (condition) list.sorted else list)
Run Code Online (Sandbox Code Playgroud)