对选项结果应用或操作



我有以下代码:

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))      
Scala 2.10将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被忽略了很多。

最新更新