我有以下代码:
class CSplit(var s1: CanvNode, var s2: CanvNode) extends SplitPane
{
topComponent = s1.merge
bottomComponent = s2.merge
def containsV(orig: MapCanvT): Option[MapCanvT] =
{
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
}
}
我想减少containsV方法的代码。我的第一个想法是使用折叠方法来缩短容器In方法。但是Option没有,也没有扩展Class Anyer。Option[t]不应该扩展任一[t,None]吗?那么至少有人可以使用"非此即彼"的折叠方法。
我最后的想法是将s1和s2视为一个列表,并对其进行查找,但我无法编译:
def containsV(orig: MapCanvT):
Option[MapCanvT] = ::[CanvNode](s1, s2).find(_ == Right(orig))
fold
添加到Option
。同时,您可以使用map(f).getOrElse(g)
代替:
// These produce identical results
o.fold(g)(x => f(x))
o.map(x => f(x)).getOrElse(g)
编辑:例如,下面三个做同样的事情:
val os: List[Option[Int]] = List(Some(5),None)
// Explicit match
os.map{ _ match {
case Some(x) => x+3
case None => 0
}}
// map+getOrElse
os.map{ _.map(_+3).getOrElse(0) }
// fold
os.map{ _.fold(0)(_+3) }
在fold
的情况下,首先为None
的情况提供默认值,然后为处理有值的情况的函数提供默认值。在每种情况下,您都应该获得List(8,0)
。
它可以使用collectFirst方法通过列表实现
def containsV(orig: MapCanvT): Option[MapCanvT]
= List(s1, s2).collectFirst {case i: MapCanvT if (i == (orig) => i}
让我们从简单的部分开始:
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
与相同
containsIn(s1) orElse containsIn(s2)
现在我们只需要处理containsIn
:
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
我们可以在Either
上使用fold
,这消除了大部分模式匹配:
cn.fold(_ => None, Some(_))
但还有orig
的东西。不过,我们可以用过滤器处理:
cn.fold(_ => None, Some(_)) filter (orig.==)
因此:
def containsV(orig: MapCanvT): Option[MapCanvT] = {
def containsIn(cn: CanvNode): Option[MapCanvT] =
cn.fold(_ => None, Some(_)) filter (orig.==)
containsIn(s1) orElse containsIn(s2)
}
我认为orElse
被忽略了很多。