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 提供有意义的好名字,而不是使用简单的元组。
只有在可以提高整体性能时才使用状态。始终将状态包含在容器内,不允许其他外部实体操纵状态。
这样你生活中的烦恼就会少一些,早点回家。
假设我有一些可重复使用的方法(在现实生活中更复杂),它接受 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 提供有意义的好名字,而不是使用简单的元组。
只有在可以提高整体性能时才使用状态。始终将状态包含在容器内,不允许其他外部实体操纵状态。
这样你生活中的烦恼就会少一些,早点回家。