习惯于执行条件转换的方法

时间:2016-11-14 18:28:25

标签: scala

我有一个对象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

当我剪切和粘贴线条时,这似乎非常麻烦,甚至容易出错。是否有更惯用的表达方式?

1 个答案:

答案 0 :(得分:3)

可以将一系列条件转换表示为Function s的组合。这样,每个转换都可以独立声明,并重新用于构建新的转换。

举个例子:

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)