[英]Idiomatic alternative to `if (x) Some(y) else None`
我发现在我的代码中反复弹出以下模式,我的直觉说必须有一些惯用的Scala方法来更好地表达这个(Monadic或其他):
val someCollection: Seq[Thing] = ...
val makeBlah: Seq[Thing] => Blah = ...
...
if (someCollection.nonEmpty) Some(makeBlah(someCollection)) else None
更具体地说,我正在寻找与使用Option[T]
可以做的事情相符的事情:
val someOption: Option[Thing] = ...
val makeBlah: Thing => Blah = ...
...
val result: Option[Blah] = someOption.map(makeBlah)
...但是基于某些谓词的评估语义而不是map
Some
/ None
模式匹配。
虽然上面的示例使用了一个集合 - 首先对它执行测试,然后可选地执行操作 - 但我并不是要暗示集合特定的用例。 您可以想象一下将Boolean
值提升或强制转换为某些monad的情况:
val aThing: Thing = ...
val makeBlah: Thing => Blah = ...
val thingTest: Thing => Boolean ...
// theoretical
implicit def optionOnBoolean(b: Boolean): MonadOps[Option[Boolean]] = ...
...
// NB: map could either have a Boolean parameter
// that's always true, or be Unit.
// Neither seem like good design
val result: Option[Blah] = thingTest(aThing).map(makeBlah(aThing))
直观地说,这对我来说似乎是一个坏主意,因为它明确地分割了数据流,因为你实际上没有任何东西可以通过map
传递。
当寻找具有“monadic-like”行为而没有闭包来捕获数据的一般方法时,必须回答要传递给map
以及它与谓词的连接的问题。 这是我想到的构造类型:
val thing: Thing = ....
val makeBlah: Thing => Blah = ...
val thingTest: (Thing) => Boolean = ...
val result: Option[Blah] = WhenOption(thing, thingTest).map(makeBlah)
我的问题:Scala中是否存在某些东西,或者是否必须冒险去Scalaz才能获得这种构造?
或者是否有一些习惯/惯用Scala的其他方法?
编辑 :我的问题接近Scala - “if(true)Some(1)”而不必键入“else None”但我希望解决在没有闭包的情况下实现它的问题。
为了完整性:
val someCollection: Seq[Thing] = ...
val makeBlah: Seq[Thing] => Blah = ...
您可以在Option
上使用一些方法:
Some(someCollection).filterNot(_.isEmpty).map(makeBlah)
或者至于理解
for(sc <- Some(someCollection) if !someCollection.isEmpty) yield makeBla(sc)
或作为模式匹配
someCollection match {
case Seq() => None
case x => Some(makeBlah(x))
}
但我认为if-then-else
方法是最可读的方法。
我会继续做你正在做的事情,除非你发现自己在相同的功能范围内重复同样的逻辑和恶心。 它可读并且有意义。 也就是说,如果你真的需要,你可以“解除” PartialFunction
(见这里 ):
def foo: PartialFunction[Seq[A], B]
def fooLifted: (Seq[A] => Option[B]) = foo.lift
现在,您所要做的就是使条件逻辑显式化
def foo ={
case seq if predicate(seq) => doStuff(seq)
}
这比你正在做的更多样板。
FWIW,我做同样的事情你建议:
implicit class RichBoolean(val b: Boolean) extends AnyVal {
def map[T](f: => T): Option[T] = if (b) Some(f) else None
def flatMap[T](f: => Option[T]): Option[T] = if (b) f else None
}
“地图”在这里感觉不对,但我想不出更好的东西。 我非常喜欢这种结构,它可以帮助您在对数据进行连续几次操作时保持“流量”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.