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

japgolly.microlibs.nonempty.NonEmptyVector.scala Maven / Gradle / Ivy

The newest version!
package japgolly.microlibs.nonempty

import japgolly.univeq.UnivEq
import scala.collection.{AbstractIterator, GenTraversableOnce}
import scala.collection.generic.CanBuildFrom
import scala.collection.immutable.Range
import scala.math.Ordering
import scalaz._
import scalaz.std.vector.{vectorEqual, vectorOrder}

final class NonEmptyVector[+A](val head: A, val tail: Vector[A]) {
  override def toString = "NonEmpty" + whole.toString

  override def hashCode = head.## * 31 + tail.##

  override def equals(o: Any) = o match {
    case that: NonEmptyVector[Any] => this.head == that.head && this.tail == that.tail
    case _ => false
  }

  def length: Int =
    tail.length + 1

  def unsafeApply(i: Int): A =
    if (i == 0)
      head
    else
      tail(i - 1)

  def apply(i: Int): Option[A] =
    try {
      Some(unsafeApply(i))
    } catch {
      case _: IndexOutOfBoundsException => None
    }

  def init: Vector[A] =
    if (tail.isEmpty)
      Vector.empty
    else
      head +: tail.init

  def initNonEmpty: Option[NonEmptyVector[A]] = NonEmptyVector option init
  def tailNonEmpty: Option[NonEmptyVector[A]] = NonEmptyVector option tail

  def map[B](f: A => B): NonEmptyVector[B] =
    NonEmptyVector(f(head), tail map f)

  def flatMap[B](f: A => NonEmptyVector[B]): NonEmptyVector[B] =
    reduceMapLeft1(f)(_ ++ _)

  def foreach[U](f: A => U): Unit = {
    f(head)
    tail foreach f
  }

  def foreachWithIndex[U](f: (A, Int) => U): Unit = {
    f(head, 0)
    var i = 0
    for (a <- tail) {
      i += 1
      f(a, i)
    }
  }

  def indices: Range =
    0 until length

  def forall(f: A => Boolean): Boolean =
    f(head) && tail.forall(f)

  def exists(f: A => Boolean): Boolean =
    f(head) || tail.exists(f)

  def find(f: A => Boolean): Option[A] =
    if (f(head)) Some(head) else tail.find(f)

  def mapTail[B >: A](f: Vector[A] => Vector[B]): NonEmptyVector[B] =
    NonEmptyVector(head, f(tail))

  def mapWithIndex[B](f: (A, Int) => B): NonEmptyVector[B] = {
    val h = f(head, 0)
    var i = 0
    var t = Vector.empty[B]
    for (a <- tail) {
      i += 1
      t :+= f(a, i)
    }
    NonEmptyVector(h, t)
  }

  def :+[B >: A](a: B): NonEmptyVector[B] =
    mapTail(_ :+ a)

  def +:[B >: A](a: B): NonEmptyVector[B] =
    NonEmptyVector(a, head +: tail)

  def ++[B >: A](as: GenTraversableOnce[B]): NonEmptyVector[B] =
    mapTail(_ ++ as)

  def ++[B >: A](b: NonEmptyVector[B]): NonEmptyVector[B] =
    ++(b.whole)

  def ++:[B >: A](as: Vector[B]): NonEmptyVector[B] =
    if (as.isEmpty) this else NonEmptyVector(as.head, as.tail ++ whole)

  def last: A =
    if (tail.isEmpty) head else tail.last

  def whole: Vector[A] =
    head +: tail

  def reverse: NonEmptyVector[A] =
    if (tail.isEmpty) this else NonEmptyVector.end(tail.reverse, head)

  def foldLeft[B](z: B)(f: (B, A) => B): B =
    tail.foldLeft(f(z, head))(f)

  def foldMapLeft1[B](g: A => B)(f: (B, A) => B): B =
    tail.foldLeft(g(head))(f)

  def reduceMapLeft1[B](f: A => B)(g: (B, B) => B): B =
    foldMapLeft1(f)((b, a) => g(b, f(a)))

  def reduce[B >: A](f: (B, B) => B): B =
    reduceMapLeft1[B](a => a)(f)

  // Reduce bullshit red in IntelliJ
//  def traverseD[L, B](f: A => L \/ B): L \/ NonEmptyVector[B] =
//    NonEmptyVector.traverse1.traverseU(this)(f)

  def intercalate[B >: A](b: B): NonEmptyVector[B] =
    intercalateF(b)(a => a)

  def intercalateF[B](b: B)(f: A => B): NonEmptyVector[B] = {
    val r = implicitly[CanBuildFrom[Nothing, B, Vector[B]]].apply()
    for (a <- tail) {
      r += b
      r += f(a)
    }
    NonEmptyVector(f(head), r.result())
  }

  def filter(f: A => Boolean): Option[NonEmptyVector[A]] =
    NonEmptyVector.option(whole filter f)

  def filterNot(f: A => Boolean): Option[NonEmptyVector[A]] =
    filter(!f(_))

  def iterator: Iterator[A] =
    whole.iterator

  def toStream = whole.toStream

  def mapToNES[B: UnivEq](f: A => B): NonEmptySet[B] =
    NonEmptySet force iterator.map(f).toSet

  def toNES[B >: A : UnivEq]: NonEmptySet[B] =
    NonEmptySet(head, tail.toSet[B])

  private def safeTrans[B](f: Vector[A] => Vector[B]): NonEmptyVector[B] =
    NonEmptyVector force f(whole)

  def sorted[B >: A](implicit ord: Ordering[B])       = safeTrans(_.sorted[B])
  def sortBy[B](f: A => B)(implicit ord: Ordering[B]) = safeTrans(_ sortBy f)
  def sortWith(lt: (A, A) => Boolean)                 = safeTrans(_ sortWith lt)

  def partitionD[B, C](f: A => B \/ C): (NonEmptyVector[B], Vector[C]) \/ (Vector[B], NonEmptyVector[C]) = {
    var bs = Vector.empty[B]
    var cs = Vector.empty[C]
    for (a <- tail)
      f(a) match {
        case -\/(b) => bs :+= b
        case \/-(c) => cs :+= c
      }
    f(head) match {
      case -\/(b) => -\/((NonEmptyVector(b, bs), cs))
      case \/-(c) => \/-((bs, NonEmptyVector(c, cs)))
    }
  }

  def partitionB(f: A => Boolean): (NonEmptyVector[A], Vector[A]) = {
    var ts = Vector.empty[A]
    var fs = Vector.empty[A]
    for (a <- tail)
      if (f(a))
        ts :+= a
      else
        fs :+= a
    if (ts.nonEmpty)
      (NonEmptyVector force ts, fs)
    else
      (NonEmptyVector force fs, ts)
  }

  /**
   * Peels away elements from the end until there are no elements left.
   *
   * Example:
   *
   * NonEmptyVector(2,4,6,8) will yield
   *
   *   NonEmptyVector(2,4,6,8)
   *   NonEmptyVector(2,4,6)
   *   NonEmptyVector(2,4)
   *   NonEmptyVector(2)
   */
  def peelFromEnd: Iterator[NonEmptyVector[A]] =
    new AbstractIterator[NonEmptyVector[A]] {
      var cur: NonEmptyVector[A] = NonEmptyVector.this
      override def hasNext = cur ne null
      override def next() = {
        val r = cur
        cur = r.initNonEmpty.orNull
        r
      }
    }

  def mkString(start: String, sep: String, end: String): String =
    whole.mkString(start, sep, end)

  def mkString(sep: String): String = mkString("", sep, "")

  def mkString: String = mkString("")
}

// =====================================================================================================================

object NonEmptyVector extends NonEmptyVectorImplicits0 {
  def one[A](h: A): NonEmptyVector[A] =
    new NonEmptyVector(h, Vector.empty)

  /** Avoids failed type-inference with NonEmptyVector(Vector.empty[Int], Vector.empty[Int]) */
  def varargs[A](h: A, t: A*): NonEmptyVector[A] =
    apply(h, t.toVector)

  def apply[A](h: A, t: A*): NonEmptyVector[A] =
    apply(h, t.toVector)

  def apply[A](h: A, t: Vector[A]): NonEmptyVector[A] =
    new NonEmptyVector(h, t)

  def endOV[A](init: Option[Vector[A]], last: A): NonEmptyVector[A] =
    init.fold(one(last))(end(_, last))

  def endO[A](init: Option[NonEmptyVector[A]], last: A): NonEmptyVector[A] =
    init.fold(one(last))(_ :+ last)

  def end[A](init: Vector[A], last: A): NonEmptyVector[A] =
    if (init.isEmpty)
      one(last)
    else
      new NonEmptyVector(init.head, init.tail :+ last)

  def maybe[A, B](v: Vector[A], empty: => B)(f: NonEmptyVector[A] => B): B =
    if (v.isEmpty) empty else f(NonEmptyVector(v.head, v.tail))

  def option[A](v: Vector[A]): Option[NonEmptyVector[A]] =
    maybe[A, Option[NonEmptyVector[A]]](v, None)(Some.apply)

  def force[A](v: Vector[A]): NonEmptyVector[A] =
    apply(v.head, v.tail)

  def unwrapOption[A](o: Option[NonEmptyVector[A]]): Vector[A] =
    o.fold(Vector.empty[A])(_.whole)

  def newBuilder[A](head: A): Builder[A] =
    new Builder(head)

  def newBuilderNE[A](as: NonEmptyVector[A]): Builder[A] = {
    val b = newBuilder(as.head)
    b ++= as.tail
    b
  }

  final class Builder[A](head: A) {
    private[this] val tail = Vector.newBuilder[A]

    def +=(a: A): Unit = {
      tail += a
      ()
    }

    def ++=(as: TraversableOnce[A]): Unit = {
      tail ++= as
      ()
    }

    def ++=(as: NonEmptyVector[A]): Unit = {
      this += as.head
      this ++= as.tail
    }

    def result(): NonEmptyVector[A] =
      NonEmptyVector(head, tail.result())
  }

  implicit def univEq[A: UnivEq]: UnivEq[NonEmptyVector[A]] =
    UnivEq.force

  implicit def semigroup[A]: Semigroup[NonEmptyVector[A]] =
    new Semigroup[NonEmptyVector[A]] {
      override def append(a: NonEmptyVector[A], b: => NonEmptyVector[A]): NonEmptyVector[A] = a ++ b
    }

  implicit def traverse1: Traverse1[NonEmptyVector] = new Traverse1[NonEmptyVector] {
    override def foldLeft[A, B](fa: NonEmptyVector[A], z: B)(f: (B, A) => B): B =
      fa.foldLeft(z)(f)

    override def foldMapRight1[A, B](fa: NonEmptyVector[A])(z: A => B)(f: (A, => B) => B): B =
      fa.init.reverseIterator.foldLeft(z(fa.last))((b, a) => f(a, b))

    override def index[A](fa: NonEmptyVector[A], i: Int): Option[A] =
      fa(i)

    override def length[A](fa: NonEmptyVector[A]) =
      fa.length

    override def map[A, B](fa: NonEmptyVector[A])(f: A => B): NonEmptyVector[B] =
      fa map f

    override def traverse1Impl[G[_], A, B](fa: NonEmptyVector[A])(f: A => G[B])(implicit ap: Apply[G]): G[NonEmptyVector[B]] = {
      val gh = f(fa.head)
      if (fa.tail.isEmpty)
        ap.map(gh)(one)
      else {
        val gz = ap.map(gh)(_ => Vector.empty[B])
        val gt = fa.tail.foldLeft(gz)((q, a) => ap.apply2(q, f(a))(_ :+ _))
        ap.apply2(gh, gt)(new NonEmptyVector(_, _))
      }
    }
  }

  object Sole {
    def unapply[A](v: NonEmptyVector[A]) = new Unapply(v)
    final class Unapply[A](val v: NonEmptyVector[A]) extends AnyVal {
      def isEmpty = v.tail.nonEmpty
      def get     = v.head
    }
  }
}

trait NonEmptyVectorImplicits1 {
  implicit def order[A: Order]: Order[NonEmptyVector[A]] =
    vectorOrder[A].contramap(_.whole)
}

trait NonEmptyVectorImplicits0 extends NonEmptyVectorImplicits1 {
  implicit def equality[A: Equal]: Equal[NonEmptyVector[A]] =
    vectorEqual[A].contramap(_.whole)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy