Scala - 多个可变参数引用或指向对象的引用的引用

时间:2016-12-30 09:13:10

标签: scala parameter-passing mutable

让我们说我有一些可重用的方法(在现实生活中更复杂)接受3个BigDecimal参数并计算一些东西。计算后输入params在内部改变,我需要所有三个外部进行下一次计算,依此类推。

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

在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)重新分配给val a = b + c

全局变量是否应答,或者是一些可变的助手持有者对象?

2 个答案:

答案 0 :(得分:1)

我没有改变它们,只是将计算结果返回到三元组或案例类实例中:

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
}

答案 1 :(得分:1)

您可以使用元组返回多个值或使用包装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)

使用case类(将这个三元组与case类包装在一起并提供好名称,这是推荐的方法,因为它可以提高代码的可维护性)

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))

一般建议

尽量避免使用突变。不可变,这是在软件增长时无bug的唯一方法。功能也变得可测试,重构也很容易。代码变得具有声明性且易于阅读。使用返回类型从函数与外部世界通信。 为返回类型类提供有意义的有意义的名称,而不是使用简单的元组。

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

这样你生活中的问题就会减少,你可以早点回家。