All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.thoughtworks.Extractor.scala Maven / Gradle / Ivy

The newest version!
package com.thoughtworks

private[thoughtworks] sealed trait LowLowPriorityExtractor {

  implicit final class FunctionToExtractor[-A, +B] private[LowLowPriorityExtractor] (underlying: A => B) {
    def extract = new Extractor[A, B] {
      override def unapply(a: A): Some[B] = {
        Some(underlying(a))
      }
    }
  }

}

private[thoughtworks] sealed trait LowPriorityExtractor extends LowLowPriorityExtractor {

  sealed trait SeqExtractor[-A, +B] {
    def unapplySeq(a: A): Option[Seq[B]]
  }

  implicit final class OptionFunctionToSeqExtractor[-A, +B] private[LowPriorityExtractor] (
      underlying: A => Option[Seq[B]]) {
    def seq = new SeqExtractor[A, B] {
      def unapplySeq(a: A) = underlying(a)
    }
  }

  implicit final class OptionFunctionToExtractor[-A, +B] private[LowPriorityExtractor] (underlying: A => Option[B]) {
    def extract = new Extractor[A, B] {
      def unapply(a: A) = underlying(a)
    }

    def forall = new Extractor[Seq[A], Seq[B]] {
      override def unapply(a: Seq[A]): Option[Seq[B]] = {
        Some(a.map {
          case OptionFunctionToExtractor.this.extract(b) => b
          case _ => return None
        })
      }
    }

  }

}

/**
  * A pattern that can be used in `match` / `case` expressions.
  */
sealed trait Extractor[-A, +B] extends (A => Option[B]) {
  def unapply(a: A): Option[B]
  final def apply(a: A) = unapply(a)
}

/**
  * Utilities to convert between `A => Option[B]`, [[scala.PartialFunction]] and [[Extractor]].
  *
  * @example
    {{{
    import com.thoughtworks.Extractor._

    // Define a PartialFunction
    val pf: PartialFunction[Int, String] = {
      case 1 => "matched by PartialFunction"
    }

    // Define an optional function
    val f: Int => Option[String] = { i =>
      if (i == 2) {
        Some("matched by optional function")
      } else {
        None
      }
    }

    // Convert an optional function to a PartialFunction
    val pf2: PartialFunction[Int, String] = Function.unlift(f)

    util.Random.nextInt(4) match {
      case pf.extract(m) => // Convert a PartialFunction to a pattern
        println(m)
      case f.extract(m) => // Convert an optional function to a pattern
        println(m)
      case pf2.extract(m) => // Convert a PartialFunction to a pattern
        throw new AssertionError("This case should never occur because it has the same condition as `f.extract`.")
      case _ =>
        println("Not matched")
    }
    }}}
  *
  */
object Extractor extends LowPriorityExtractor {

  implicit final class PartialFunctionToExtractor[-A, +B] private[Extractor] (underlying: PartialFunction[A, B]) {
    def extract = new Extractor[A, B] {
      def unapply(a: A) = underlying.lift(a)
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy