<commit_before>package busymachines.result

import scala.util.{Failure, Success, Try}
import scala.util.control.NonFatal
import busymachines.core._

/**
  * The reason I chose this instead of aliasing [[Either]] companion object
  * is to avoid situations where implicit ops defined on [[scala.util.Either#type]]
  * conflict with any operations I'd like to define here.
  *
  * Plus, I can seriously help out type inference by writing all method signatures in
  * terms of the rhs type only.
  *
  * @author <NAME>, <EMAIL>, <EMAIL>
  * @since 09 Jan 2018
  */
object Result {
  def pure[T](t:    T): Result[T] = Correct(t)
  def correct[T](t: T): Result[T] = Correct(t)

  def fail[T](a:      Anomaly): Result[T] = Incorrect(a)
  def incorrect[T](a: Anomaly): Result[T] = Incorrect(a)

  def unit: Result[Unit] = Correct(())

  /**
    * Useful when one wants to do interop with unknown 3rd party code and you cannot
    * trust it not to throw exceptions in your face.
    */
  def apply[T](thunk: => T): Result[T] = {
    try {
      Result.pure(thunk)
    } catch {
      case a: Anomaly                  => Result.incorrect(a)
      case t: Throwable if NonFatal(t) => Result.incorrect(CatastrophicError(t))
    }
  }

  def fromEither[L, R](elr: Either[L, R])(implicit ev: L <:< Throwable): Result[R] = {
    elr match {
      case Left(left) =>
        ev(left) match {
          case a: Anomaly => Result incorrect a
          case NonFatal(t) => Result incorrect CatastrophicError(t)
        }
      case Right(value) => Result.pure(value)
    }
  }

  def fromEither[L, R](elr: Either[L, R], transformLeft: L => Anomaly): Result[R] = {
    elr match {
      case Left(left)   => Result.incorrect(transformLeft(left))
      case Right(value) => Result.pure(value)
    }
  }

  def fromTry[T](t: Try[T]): Result[T] = t match {
    case Failure(a: Anomaly) => Result.incorrect(a)
    case Failure(NonFatal(r)) => Result.incorrect(CatastrophicError(r))
    case Success(value)       => Result.pure(value)
  }

  def fromOption[T](opt: Option[T], ifNone: => Anomaly): Result[T] = {
    opt match {
      case None    => Result.incorrect(ifNone)
      case Some(v) => Result.pure(v)
    }
  }

}

/**
  *
  *<commit_msg>Add Result.cond method #53<commit_after>package busymachines.result

import scala.util.{Failure, Success, Try}
import scala.util.control.NonFatal
import busymachines.core._

/**
  * The reason this approach was chosen instead of aliasing the [[Either]] companion object
  * is to avoid situations where implicit ops defined on [[scala.util.Either#type]]
  * conflict with any operations defined here.
  *
  * Plus, I can seriously help out type inference by writing all method signatures in
  * terms of the rhs type only.
  *
  * @author <NAME>, <EMAIL>, <EMAIL>
  * @since 09 Jan 2018
  */
object Result {
  def pure[T](t:    T): Result[T] = Correct(t)
  def correct[T](t: T): Result[T] = Correct(t)

  def fail[T](a:      Anomaly): Result[T] = Incorrect(a)
  def incorrect[T](a: Anomaly): Result[T] = Incorrect(a)

  def unit: Result[Unit] = Correct(())

  /**
    * Useful when one wants to do interop with unknown 3rd party code and you cannot
    * trust it not to throw exceptions in your face.
    */
  def apply[T](thunk: => T): Result[T] = {
    try {
      Result.pure(thunk)
    } catch {
      case a: Anomaly                  => Result.incorrect(a)
      case t: Throwable if NonFatal(t) => Result.incorrect(CatastrophicError(t))
    }
  }

  def fromEither[L, R](elr: Either[L, R])(implicit ev: L <:< Throwable): Result[R] = {
    elr match {
      case Left(left) =>
        ev(left) match {
          case a: Anomaly => Result incorrect a
          case NonFatal(t) => Result incorrect CatastrophicError(t)
        }
      case Right(value) => Result.pure(value)
    }
  }

  def fromEither[L, R](elr: Either[L, R], transformLeft: L => Anomaly): Result[R] = {
    elr match {
      case Left(left)   => Result.incorrect(transformLeft(left))
      case Right(value) => Result.pure(value)
    }
  }

  def fromTry[T](t: Try[T]): Result[T] = t match {
    case Failure(a: Anomaly) => Result.incorrect(a)
    case Failure(NonFatal(r)) => Result.incorrect(CatastrophicError(r))
    case Success(value)       => Result.pure(value)
  }

  def fromOption[T](opt: Option[T], ifNone: => Anomaly): Result[T] = {
    opt match {
      case None    => Result.incorrect(ifNone)
      case Some(v) => Result.pure(v)
    }
  }

  def cond[T](test: Boolean, correct: => T, anomaly: => Anomaly): Result[T] =
    Either.cond[Anomaly, T](test, correct, anomaly)

}

/**
  *
  *
{'fraction_non_alphanumeric': 0.14090019569471623, 'fraction_numerical': 0.0034790171776473144, 'mean_word_length': 3.003481288076588, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6273451', 'n_tokens_mistral': 1646, 'n_tokens_neox': 1544, 'n_words': 438}