应用或操作选项结果

时间:2012-08-23 22:01:52

标签: scala scala-option

我有以下代码:

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方法的代码。我的第一个想法是使用fold方法来缩短containsIn方法。但Option没有一个,也没有扩展Class Either。 Option [T]不应该扩展[T,None]吗?然后至少有一个人可以使用Either的折叠方法。

我最后的想法是将s1和s2视为一个List并找到它,但我无法将其编译:

def containsV(orig: MapCanvT):
  Option[MapCanvT] = ::[CanvNode](s1, s2).find(_ == Right(orig))      

3 个答案:

答案 0 :(得分:5)

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)

答案 1 :(得分:2)

可以使用collectFirst方法

使用列表实现
def containsV(orig: MapCanvT): Option[MapCanvT]
  = List(s1, s2).collectFirst {case i: MapCanvT if (i == (orig) => i}    

答案 2 :(得分:1)

让我们从简单的部分开始:

  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                 
  }

我们可以在fold上使用Either,它可以摆脱大多数模式匹配:

 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被忽视了。