summaryrefslogblamecommitdiff
path: root/src/library/scala/util/Try.scala
blob: efa2fcabb8f8051fab3a32577ef4dccd6c43c426 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                                          
                  

 
 



                     
   
                                                                                  
                                                                  


                               
                                                               



                        
                                                               



                        
                                                                                        
     
                                                                        

     
                                                                                          
     
            



                                                      
                                 

     
                                                                                                                



                                        
                                                                                                     


                               
                                                   
 
                                      
 
     
                                                                    



                                     
                                                                    
     
                                                             

     
                                                                                                                    
     
                                                                                 

     
                                                                                                              
     
                                                                             
 
     
                                                                                                   
     
                                                   
 
                                                
 
     
                                                                                                              
                         
     
                                                     

     
                                                                    
                                                             

                                                   
 
                            

 
 


                                                                  

                                                                                     
                                                                                      

                            
     
   


                                                                           
                                      

                                                                           
                                            
                                                                               

                                                 


            
                                              
                                                 

 
 




                                                                                                  
                                          
                

                          
     


                                                           
                                                     

                                                                                           
                                       

                                                                                    
                                                                                    
                                                 
                                                                                           

 


















                                                                        
 
            
 




                                   
 
 
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2008-2011, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala.util



import collection.Seq



/**
 * The `Try` type represents a computation that may either result in an exception,
 * or return a success value. It's analagous to the `Either` type.
 */
sealed abstract class Try[+T] {
  /**
   * Returns true if the `Try` is a `Failure`, false otherwise.
   */
  def isFailure: Boolean

  /**
   * Returns true if the `Try` is a `Success`, false otherwise.
   */
  def isSuccess: Boolean

  /**
   * Returns the value from this `Success` or the given argument if this is a `Failure`.
   */
  def getOrElse[U >: T](default: => U) = if (isSuccess) get else default

  /**
   * Returns the value from this `Success` or throws the exception if this is a `Failure`.
   */
  def get: T

  /**
   * Applies the given function f if this is a Result.
   */
  def foreach[U](f: T => U): Unit

  /**
   * Returns the given function applied to the value from this `Success` or returns this if this is a `Failure`.
   */
  def flatMap[U](f: T => Try[U]): Try[U]

  /**
   * Maps the given function to the value from this `Success` or returns this if this is a `Failure`.
   */
  def map[U](f: T => U): Try[U]

  def collect[U](pf: PartialFunction[T, U]): Try[U]

  def exists(p: T => Boolean): Boolean

  /**
   * Converts this to a `Failure` if the predicate is not satisfied.
   */
  def filter(p: T => Boolean): Try[T]

  /**
   * Converts this to a `Failure` if the predicate is not satisfied.
   */
  def filterNot(p: T => Boolean): Try[T] = filter(x => !p(x))

  /**
   * Calls the exceptionHandler with the exception if this is a `Failure`. This is like `flatMap` for the exception.
   */
  def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U]

  /**
   * Calls the exceptionHandler with the exception if this is a `Failure`. This is like map for the exception.
   */
  def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U]

  /**
   * Returns `None` if this is a `Failure` or a `Some` containing the value if this is a `Success`.
   */
  def toOption = if (isSuccess) Some(get) else None

  def toSeq = if (isSuccess) Seq(get) else Seq()

  /**
   * Returns the given function applied to the value from this Success or returns this if this is a `Failure`.
   * Alias for `flatMap`.
   */
  def andThen[U](f: T => Try[U]): Try[U] = flatMap(f)

  /**
   * Transforms a nested `Try`, i.e., a `Try` of type `Try[Try[T]]`,
   * into an un-nested `Try`, i.e., a `Try` of type `Try[T]`.
   */
  def flatten[U](implicit ev: T <:< Try[U]): Try[U]

  def failed: Try[Throwable]
}


final class Failure[+T](val exception: Throwable) extends Try[T] {
  def isFailure: Boolean = true
  def isSuccess: Boolean = false
  def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U] = {
    try {
      if (rescueException.isDefinedAt(exception)) rescueException(exception) else this
    } catch {
      case e2 => Failure(e2)
    }
  }
  def get: T = throw exception
  def flatMap[U](f: T => Try[U]): Try[U] = Failure[U](exception)
  def flatten[U](implicit ev: T <:< Try[U]): Try[U] = Failure[U](exception)
  def foreach[U](f: T => U): Unit = {}
  def map[U](f: T => U): Try[U] = Failure[U](exception)
  def collect[U](pf: PartialFunction[T, U]): Try[U] = Failure[U](exception)
  def filter(p: T => Boolean): Try[T] = this
  def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] =
    if (rescueException.isDefinedAt(exception)) {
      Try(rescueException(exception))
    } else {
      this
    }
  def exists(p: T => Boolean): Boolean = false
  def failed: Try[Throwable] = Success(exception)
}


final class Success[+T](value: T) extends Try[T] {
  def isFailure: Boolean = false
  def isSuccess: Boolean = true
  def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U] = Success(value)
  def get = value
  def flatMap[U](f: T => Try[U]): Try[U] =
    try f(value)
    catch {
      case e => Failure(e)
    }
  def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value
  def foreach[U](f: T => U): Unit = f(value)
  def map[U](f: T => U): Try[U] = Try[U](f(value))
  def collect[U](pf: PartialFunction[T, U]): Try[U] =
    if (pf isDefinedAt value) Success(pf(value))
    else Failure[U](new NoSuchElementException("Partial function not defined at " + value))
  def filter(p: T => Boolean): Try[T] =
    if (p(value)) this
    else Failure(new NoSuchElementException("Predicate does not hold for " + value))
  def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] = this
  def exists(p: T => Boolean): Boolean = p(value)
  def failed: Try[Throwable] = Failure(new UnsupportedOperationException("Success.failed"))
}

object Failure {
  def apply[T](e: Throwable): Failure[T] = new Failure(e)
  def unapply(scrutinizee: Any): Option[Throwable] = scrutinizee match {
    case Right(_) => None
    case Left(e) => Some(e.asInstanceOf[Throwable])
    case s: Success[_] => None
    case f: Failure[_] => Some(f.exception)
  }
}

object Success {
  def apply[T](value: T): Success[T] = new Success(value)
  def unapply[T](scrutinizee: Any): Option[T] = scrutinizee match {
    case Right(v) => Some(v.asInstanceOf[T])
    case Left(_) => None
    case s: Success[_] => Some(s.get.asInstanceOf[T])
    case f: Failure[Throwable] => None
  }
}

object Try {

  def apply[T](r: => T): Try[T] = {
    try { Success(r) } catch {
      case e => Failure(e)
    }
  }

}