Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 112 lines (101 sloc) 4.639 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */



package scala

/** A partial function of type `PartialFunction[A, B]` is a
* unary function where the domain does not necessarily include all values of type
* `A`. The function `isDefinedAt` allows to
* test dynamically if a value is in the domain of the function.
*
* @author Martin Odersky
* @version 1.0, 16/07/2003
*/
trait PartialFunction[-A, +B] extends (A => B) {

  /** Checks if a value is contained in the function's domain.
*
* @param x the value to test
* @return `true`, iff `x` is in the domain of this function, `false` otherwise.
*/
  def isDefinedAt(x: A): Boolean

  /** Composes this partial function with a fallback partial function which gets applied where this partial function
* is not defined.
*
* @param that the fallback function
* @tparam A1 the argument type of the fallback function
* @tparam B1 the result type of the fallback function
* @return a partial function which has as domain the union of the domains
* of this partial function and `that`. The resulting partial function
* takes `x` to `this(x)` where `this` is defined, and to `that(x)` where it is not.
*/
  def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] =
    new PartialFunction[A1, B1] {
    def isDefinedAt(x: A1): Boolean =
      PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x)
    def apply(x: A1): B1 =
      if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x)
      else that.apply(x)
  }

  /** Composes this partial function with a transformation function that gets applied
* to results of this partial function.
* @param k the transformation function
* @tparam C the result type of the transformation function.
* @return a partial function with the same domain as this partial function, which maps
* arguments `x` to `k(this(x))`.
*/
  override def andThen[C](k: B => C) : PartialFunction[A, C] = new PartialFunction[A, C] {
    def isDefinedAt(x: A): Boolean = PartialFunction.this.isDefinedAt(x)
    def apply(x: A): C = k(PartialFunction.this.apply(x))
  }

  /** Turns this partial function into an plain function returning an `Option` result.
* @see Function.unlift
* @return a function that takes an argument `x` to `Some(this(x))` if `this`
* is defined for `x`, and to `None` otherwise.
*/
  def lift: A => Option[B] = new (A => Option[B]) {
    def apply(x: A): Option[B] = if (isDefinedAt(x)) Some(PartialFunction.this.apply(x)) else None
  }
}

/** A few handy operations which leverage the extra bit of information
* available in partial functions. Examples:
*
* <pre>
* import PartialFunction._
*
* def strangeConditional(other: Any): Boolean = cond(other) {
* case x: String if x == "abc" || x == "def" => true
* case x: Int => true
* }
* def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
* </pre>
*
* @author Paul Phillips
* @since 2.8
*/
object PartialFunction
{
  /** Creates a Boolean test based on a value and a partial function.
* It behaves like a 'match' statement with an implied 'case _ => false'
* following the supplied cases.
*
* @param x the value to test
* @param pf the partial function
* @return true, iff `x` is in the domain of `pf` and `pf(x) == true`.
*/
  def cond[T](x: T)(pf: PartialFunction[T, Boolean]): Boolean =
    (pf isDefinedAt x) && pf(x)

  /** Transforms a PartialFunction[T, U] `pf' into Function1[T, Option[U]] `f'
* whose result is Some(x) if the argument is in pf's domain and None otherwise,
* and applies it to the value `x'. In effect, it is a 'match' statement
* which wraps all case results in Some(_) and adds 'case _ => None' to the end.
*
* @param x the value to test
* @param pf the PartialFunction[T, U]
* @return `Some(pf(x))` if `pf isDefinedAt x`, `None` otherwise.
*/
  def condOpt[T,U](x: T)(pf: PartialFunction[T, U]): Option[U] =
    if (pf isDefinedAt x) Some(pf(x)) else None
}
Something went wrong with that request. Please try again.