首页 文章

DRY使用Option的值的多个字段

提问于
浏览
0

Background

我'm using a java web UI library (Vaadin, but that'无关紧要 - 我没有使用Scaladin附加组件,其中 TextField 有一个方法 setValue(String) 来设置当前文本值 .

由于它是一个java库,它没有 Option 的概念,但可以表示 null 值,例如,一个空字符串(它's configurable). So I'写了一个隐式包装类,如下所示:

implicit class ExtendedTextField(self: TextField) {
    def :=(value: String) = self.setValue(value)
    def :=(maybeValue: Option[String]) = self.setValue(maybeValue.orNull)
}

这允许我直接在TextField实例上使用 := 运算符设置值,并允许我在单个位置处理Option to null转换 .

Problem

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

fieldA := (for (x <- maybeX) yield x.valueA)
fieldB := (for (x <- maybeX) yield x.valueB)
fieldC := (for (x <- maybeX) yield x.valueC)
...

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

fieldD := (for (x <- maybeX) yield x.valueD).flatten

(我可以简单地总是调用 flatten ,但如果没有嵌套选项则不会产生影响)

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

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

1 回答

  • 2

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

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

    对于你在x flatMap 中的一个选项的情况,它会得到与map flatten相同的结果:

    fieldD := x.flatMap(_.valueD)
    

    您可能能够创建一个执行此操作的宏,但您将根据代码的理解程度来交换此重复,并且增益可能会非常小 .

相关问题