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

org.rogach.scallop.ScallopOption.scala Maven / Gradle / Ivy

There is a newer version: 5.1.0
Show newest version
package org.rogach.scallop

/** A class to hold a reference to not-yet-computed option values.
  *
  * Basically, this is a lazy option - it batches up all operations,
  * and evaluates the value only as the last resort.
  * @param nm Name for the option
  * @param _transformCount Count of .map, .filter, etc. operations applied to this option
  * @param cliOption option descriptor (names, converters, validatiors, etc.)
  */
abstract class ScallopOption[A](
  nm: () => String,
  private[scallop] val cliOption: Option[CliOption],
  val _transformCount: Int = 0
) extends ScallopOptionBase { opt =>

  private[scallop] var _name: () => String = nm

  lazy val fn: String => Option[A] = x => None
  lazy val supplied: String => Boolean = x => false

  /** Name for the option */
  def name = _name()

  private lazy val value: Option[A] = fn(name)

  /** Retreive the underlying value as an option */
  @deprecated("use .toOption instead", "1.0.2")
  def get = value

  /** Retreive the underlying value as a scala Option */
  def toOption = value

  /** Retreive the underlying value. Use only if you are completely sure that there is a value. */
  def apply() = value.get

  /** Retrieve the underlying value if the option is nonempty, otherwise return the result of evaluating `default`. */
  def getOrElse(default: => A): A = value.getOrElse(default)

  /** Tests whether the underlying value was explicitly supplied by user. */
  def isSupplied = supplied(name)

  private def mapResult[B](transformer: Option[A] => Option[B]) =
    new ScallopOption[B](() => name, cliOption, _transformCount + 1) {
      override lazy val fn = opt.fn andThen transformer
      override lazy val supplied = opt.supplied
    }

  /** Returns ScallopOption, that contains the result of applying ```pf```
    * to the value, if this option is non-empty and pf is defined for that value.
    * Returns empty ScallopOption otherwise.
    *
    * @param pf the partial function
    */
  def collect[B](pf: PartialFunction[A,B]) = mapResult(_.collect(pf))

  /** Returns ScallopOption, that contains the value if applying
    * predicate p to this value returned true. No value otherwise.
    *
    * @param p the predicate used for testing
    */
  def filter(p: A => Boolean) = mapResult(_.filter(p))

  /** Returns ScallopOption, that contains the value if applying
    * predicate p to this value returned false. No value otherwise.
    *
    * @param p the predicate used for testing
    */
  def filterNot(p: A => Boolean) = mapResult(_.filterNot(p))

  def withFilter(p: A => Boolean) = new WithFilter(p)

  class WithFilter(p: A => Boolean) {
    def map[B](f: A => B) = opt filter p map f
    def flatMap[B](f: A => ScallopOption[B]) = opt filter p flatMap f
    def foreach(f: A => Unit) = opt filter p foreach f
    def withFilter(q: A => Boolean) = new WithFilter(x => p(x) && q(x))
  }

  /** Returns ScallopOption, that contains the result of applying
    * ```f``` to this option's value, if this option is non-empty.
    * Returns ScallopOption with no value otherwise.
    *
    * @param f the function to apply
    */
  def map[B](f: A => B) = mapResult(_.map(f))

  /** Apply the given procedure f to the option's value, if it is nonempty.
    */
  def foreach(f: A => Unit) = opt.value.foreach(f)

  /** Returns the result of applying f th this options value if
    * this option is non-empty.
    */
  def flatMap[B](f: A => ScallopOption[B]): ScallopOption[B] =
    mapResult(_.flatMap(x => f(x).toOption))

  /** Returns ScallopOption with this value if it is non-empty,
    * or with the value of the alternative option. If it is
    * empty too, the resulting ScallopOption will contain None.
    *
    * @param alternative the alternative expression
    */
  def orElse[B >: A](alternative: => Option[B]) = mapResult(_.orElse(alternative))

  /** A convenience method to check whether the underlying option
    * is defined. Just an alias for opt.get.isDefined.
    */
  def isDefined = value.isDefined

  /** A convenience method to check whether the underlying option is
    * empty. Just an alias for !opt.isDefined.
    */
  def isEmpty = !isDefined

  override def toString = opt.toOption match {
    case Some(x) => Util.format("ScallopSome(%s)", x)
    case None => "ScallopNone"
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy