我有一个对象x
。我将对它进行一系列的改造。这可以很容易地表达为
x.transformA.transformB.transformC
但是,在每次转换之前,我还应该检查条件。仅当条件为真时我才应该执行转换。我有两种方式来表达这一点。第一个是将 x 定义为 var。
var x = anObject
if (x.condA) x = x.transformA
if (x.condB) x = x.transformB
if (x.condC) x = x.transformC
// final result in x
或者,为了避免 var,我定义了一系列中间变量
val x0 = anObject
val x1 = if (x0.condA) x0.transformA else x0
val x2 = if (x1.condB) x1.transformB else x1
val x3 = if (x2.condC) x2.transformC else x2
// final result in x3
这似乎相当麻烦,甚至在剪切和粘贴线条时容易出错。有更惯用的表达方式吗?
最佳答案
可以将一系列条件转换表达为函数
的组合。这样每个转换都可以独立声明,并重用来构建新的转换。
举个例子:
val ta: MyClass => MyClass = {case x if x.condA => x.transformA
case x => x}
val tb: MyClass => MyClass = {case x if x.condB => x.transformB
case x => x}
val tc: MyClass => MyClass = {case x if x.condC => x.transformC
case x => x}
然后我们可以组合这些来形成我们的转换:
val transformation = ta andThen tb andThen tc
val transformedObj = transformation(x)
我们可以从上面看到我们一遍又一遍地重复相同的模式。为了避免这种情况,我们可以创建一个函数来创建部分函数,从而减少样板代码:
def mkTf[T](cond: T => Boolean, transf: T => T): T => T = {
case x if cond(x) => transf(x)
case x => x
}
然后我们可以将我们的组合重写为:
val transformation = mkTf[MyClass](_.condA,_.transformA) andThen
mkTf[MyClass](_.condB,_.transformB) andThen
mkTf[MyClass](_.condC,_.transformC)
关于scala - 执行条件转换的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40595402/