DRY使用Option的值的多个字段

时间:2014-09-14 15:58:29

标签: scala scala-collections scala-option

背景

我正在使用一个java web UI库(Vaadin,但这不相关 - 我没有使用Scaladin插件),其中TextField有一个方法setValue(String)来设置当前文本值。

由于它是一个java库,它没有Option的概念,但可以表示null值,例如implicit class ExtendedTextField(self: TextField) { def :=(value: String) = self.setValue(value) def :=(maybeValue: Option[String]) = self.setValue(maybeValue.orNull) } 。一个空字符串(它是可配置的)。所以我编写了一个隐式包装类,如下所示:

:=

这允许我直接在TextField实例上使用fieldA := (for (x <- maybeX) yield x.valueA) fieldB := (for (x <- maybeX) yield x.valueB) fieldC := (for (x <- maybeX) yield x.valueC) ... 运算符设置值,并允许我在一个地方处理Option to null转换。

问题

当我有例如一个带有一堆文本字段的表单,显示某个X类型对象的值,如果我有一个Option [X],我就是这样做的:

:=

换句话说,我想用Some(字符串)调用fieldD := (for (x <- maybeX) yield x.valueD).flatten ,以防我有可能是一些但是如果MaybeX是none则使用None。另外,假设x.valueD实际上是一个Option [String],我会调用

flatten

(我可以随时调用{{1}},但如果没有嵌套选项则不会产生效果)

有没有更好的方法来写这个,摆脱所有重复的理解和扁平化的结果?也许使用宏?

我不想使用反射(我确信可以将所有字段放在一个序列中,用包含属性名称的序列压缩它,然后使用返回None或者函数的函数映射它relflection查找,并使结果变平。)

1 个答案:

答案 0 :(得分:2)

这是一样紧凑,因为它是一组你想要执行的不同地图变换,如果它有一个值。你可以用map而不是理解来缩短它:

fieldA := x.map(_.valueA)
fieldB := x.map(_.valueB)
fieldC := x.map(_.valueC)

并且对于x flatMap内部选项的情况,它可以获得与map + flatten相同的结果:

fieldD := x.flatMap(_.valueD)

您可以创建一个执行此操作的宏,但您将根据代码的理解程度进行交易,并且获得的收益可能非常小。