我有 configurer
支持像这样的链式:
val configurer = Configurer("init").propA("a").propB(3).propC("bla-bla")
这是我无法更改的第 3 方库。
我有我的
case class Config(propA: Option[String], propB: Option[Int], propC: Option[String])
现在我需要构建我的
configurer
给定 config
对象,方法 propX
如果在 config
中设置了相应的值,则应调用.以功能方式做到这一点的最佳方法是什么?
我不喜欢这个
val configurer = Configurer("init")
val withPropA = config.propA.map(configurer.propA).getOrElse(configure)
val withPropB = config.propB.map(configurer.propB).getOrElse(withPropA)
val withPropC = config.propC.map(configurer.propC).getOrElse(withPropB)
只是觉得应该有一种优雅的方式。
最佳答案
由于您特别询问以功能方式执行此操作,因此我建议对每个转换 Some
的选项使用折叠。进入所需的功能和 None
进入 identity
:
config.propA.fold(identity[Configurer] _)(a => _ propA a) andThen
config.propB.fold(identity[Configurer] _)(b => _ propB b) andThen
config.propC.fold(identity[Configurer] _)(c => _ propC c)
如果你真的很喜欢冒险,你可以用 Scalaz 让它更优雅一点:
import scalaz._, Scalaz._
config.propA.map(a => Endo[Configurer](_ propA a)).orZero |+|
config.propB.map(b => Endo[Configurer](_ propB b)).orZero |+|
config.propC.map(c => Endo[Configurer](_ propC c)).orZero
不过,在实际代码中,您可能希望使用 Eugene 的解决方案,因为您只是在包装一个并不理想的 API,而且重要的是从现在开始变得清晰。
关于scala - 链式 + Scala 选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26181024/