Scala - 多个可变参数引用或对象指针的按引用传递

Scala - multiple mutable parameter reference or pass-by-reference of pointers to objects

假设我有一些可重复使用的方法(在现实生活中更复杂),它接受 3 个 BigDecimal 参数并计算一些东西。计算后输入参数在内部发生变化,我需要所有三个在外部进行下一次计算等等。

如果它只是一个参数,我可以将它 return 作为 return 值。

在 Scala 中执行此操作的惯用方法是什么?

object MutableTest extends App {

  def mutableMethodWithComplicatedButReusableLogic(a: BigDecimal, b: BigDecimal, c: BigDecimal) = {
    a = b + c
    c = b * a
    b = 0
    //All three of changed args should be available outside
  }

  var a: BigDecimal = 10
  var b: BigDecimal = 11
  var c: BigDecimal = 12

  //1. step
  mutableMethodWithComplicatedButReusableLogic(a, b, c)

  //2. step a, b, c should change in step 1 and
  mutableMethodWithComplicatedButReusableLogic(a*b, b, c -1)
  ....

}

这当然以:编译时错误:(9, 7) reassignment to val a = b + c

是全局变量答案,还是一些可变的助手对象?

我不会改变它们,只是 return 计算结果是一个三元组或一个案例 class 实例:

def mutableMethodWithComplicatedButReusableLogic(
    a: BigDecimal, b: BigDecimal, c: BigDecimal
): (BigDecimal, BigDecimal, BigDecimal) = {
  val newA = ... //Compute a
  val newB = ... //Compute b
  val newC = ... //Compute c
  (newA, newB, newC) // Or whatever other cmputation
}

您可以将元组用于 return 多个值或使用一些包装器 class 来包装 a、b 和 c。

def mutableMethodWithComplicatedButReusableLogic(a: BigDecimal, b: BigDecimal, c: BigDecimal): (BigDecimal, BigDecimal, BigDecimal) = {
 (b + c, 0, b * (b + c))
}

用法:

val (a, b, c) = mutableMethodWithComplicatedButReusableLogic(1, 2, 3)

Using case class(即用 case class 包裹这个三元组并提供好听的名字,这是推荐的方式,因为它可以提高代码的可维护性)

case class Wrapper (val a: BigDecimal, val b: BigDecimal, val c: BigDecimal)

def mutableMethodWithComplicatedButReusableLogic(wrapper: Wrapper): Wrapper = {
  Wrapper((wrapper.b + wrapper.c, 0, wrapper.b * (wrapper.b + wraper.c)))
}

用法:

val Wrapper(a, b, c) = mutableMethodWithComplicatedButReusableLogic(Wrapper(1, 2, 3))

一般建议

尽可能避免使用突变。不可变,这是在软件增长时避免错误的唯一方法。功能也变得可测试并且重构很容易。代码变得声明式且易于阅读。使用 return 类型从函数与外界通信。 为 return 类型 class 提供有意义的好名字,而不是使用简单的元组。

只有在可以提高整体性能时才使用状态。始终将状态包含在容器内,不允许其他外部实体操纵状态。

这样你生活中的烦恼就会少一些,早点回家。