
ops.View.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of psp-std_2.11 Show documentation
Show all versions of psp-std_2.11 Show documentation
psp's non-standard standard library
The newest version!
package psp
package std
package ops
import api._, all._, StdShow._, StdEq._
trait ViewOps[+A] extends Any {
def xs: View[A]
private def directIsEmpty: Boolean = {
xs foreach (_ => return false)
true
}
def fold[@fspec B](implicit z: Empty[B]): HasInitialValue[A, B] = foldFrom(z.empty)
def zfirst[B](pf: A ?=> B)(implicit z: Empty[B]): B = find(pf.isDefinedAt).fold(z.empty)(pf)
def zfoldl[B](f: (B, A) => B)(implicit z: Empty[B]): B = foldl(z.empty)(f)
def zfoldr[B](f: (A, B) => B)(implicit z: Empty[B]): B = foldr(z.empty)(f)
def isEmpty: Boolean = xs.size.isZero || directIsEmpty
def nonEmpty: Boolean = xs.size.isNonZero || !directIsEmpty
def apply(index: Index): A = xs drop index.sizeExcluding head
def count(p: ToBool[A]): Int = foldl[Int](0)((res, x) => if (p(x)) res + 1 else res)
def dropIndex(index: Index): View[A] = xs splitAt index mapRight (_ drop 1) rejoin
def exists(p: ToBool[A]): Boolean = foldl(false)((res, x) => if (p(x)) return true else res)
def filter(p: ToBool[A]): View[A] = xs withFilter p
def filterNot(p: ToBool[A]): View[A] = xs withFilter !p
def find(p: ToBool[A]): Option[A] = foldl(none[A])((res, x) => if (p(x)) return Some(x) else res)
def first[B](pf: A ?=> B): Option[B] = find(pf.isDefinedAt) map pf
def foldFrom[@fspec B](zero: B): HasInitialValue[A, B] = new HasInitialValue(xs, zero)
def foldl[@fspec B](zero: B)(f: (B, A) => B): B = foldFrom(zero) left f
def foldr[@fspec B](zero: B)(f: (A, B) => B): B = foldFrom(zero) right f
def forall(p: ToBool[A]): Boolean = foldl(true)((_, x) => p(x) || { return false })
def forallTrue(implicit ev: A <:< Boolean): Boolean = forall(ev)
def gatherClass[B: CTag] : View[B] = xs collect classFilter[B]
def grep(regex: Regex)(implicit z: Show[A]): View[A] = xs filter (regex isMatch _)
def head: A = (xs take 1).force.head
def indexWhere(p: ToBool[A]): Index = zipIndex findLeft p map snd or NoIndex
def indexed: WithIndex[A] = new WithIndex[A](xs)
def indicesWhere(p: ToBool[A]): View[Index] = zipIndex filterLeft p rights
def init: View[A] = xs dropRight 1
def join_s(implicit z: Show[A]): String = this mk_s ""
def last: A = xs takeRight 1 head
def mapApply[B, C](x: B)(implicit ev: A <:< (B => C)): View[C] = xs map (f => ev(f)(x))
def mapNow[B](f: A => B): Vec[B] = xs map f toVec
def mapZip[B](f: A => B): ZipView[A, B] = Zip.zip2(xs, xs map f)
def mk_s(sep: Char)(implicit z: Show[A]): String = this mk_s sep.to_s
def mk_s(sep: String)(implicit z: Show[A]): String = (xs map z.show).zfoldl[String]((res, x) => if (res == "") x else res append sep append x)
def slice(range: VindexRange): View[A] = xs drop range.startInt take range.size
def sliceWhile(p: ToBool[A], q: ToBool[A]): View[A] = xs dropWhile p takeWhile q
def tail: View[A] = xs drop 1
def takeToFirst(p: ToBool[A]): View[A] = xs span !p mapRight (_ take 1) rejoin
def tee(f: A => String): View[A] = xs map (x => sideEffect(x, println(f(x))))
def toRefs: View[Ref[A]] = xs map (_.toRef)
def unzip[L, R](implicit z: Splitter[A, L, R]): View[L] -> View[R] = zipped[L, R] |> (x => x.lefts -> x.rights)
def withSize(size: Size): View[A] = new Each.Impl[A](size, xs foreach _)
def zipIndex: ZipView[A, Index] = xs zip indices.all
def zip[B](ys: View[B]): ZipView[A, B] = Zip.zip2[A, B](xs, ys)
def zipped[L, R](implicit z: Splitter[A, L, R]): ZipView[L, R] = Zip.zip0[A, L, R](xs)(z)
}
final class IViewOps[A](val xs: View[A]) extends ViewOps[A] {
def +:(elem: A): View[A] = view(elem) ++ xs
def :+(elem: A): View[A] = xs ++ view(elem)
def cross[B](ys: View[B]): View[A -> B] = for (x <- xs ; y <- ys) yield x -> y
def findOr(p: ToBool[A], alt: => A): A = find(p) | alt
def gather[B](p: Partial[A, View[B]]): View[B] = xs flatMap p.zapply
def intersperse(ys: View[A]): View[A] = Split(xs, ys).intersperse
def mapBy[B: Eq, C](f: A => B, g: View[A] => C): ExMap[B, C] = groupBy[B](f) map g // Probably this should be groupBy
def mapPartial(pf: Partial[A, A]): View[A] = xs map (x => pf.applyOr(x, x))
def maxOf[B: Order](f: A => B): B = xs map f max
def memo: Indexed.Memo[A] = new Indexed.Memo(xs)
def minOf[B: Order](f: A => B): B = xs map f min
def product(implicit z: MultiplicativeMonoid[A]): A = z prod xs.trav
def quotientSet(implicit z: Eq[A]): View[ExSet[A]] = groupBy[A](identity).values map (_.toExSet)
def reducel(f: BinOp[A]): A = tail.foldl(head)(f)
def reducer(f: BinOp[A]): A = init.foldr(last)(f)
def sortBy[B](f: A => B)(implicit z: Order[B]): View[A] = orderOps(orderBy[A](f)).sorted
def sortWith(cmp: OrderRelation[A]): View[A] = orderOps(Order(cmp)).sorted
def splitAround(index: Index): A -> Split[A] = splitAt(index) |> (lr => (lr onRight (_.head)) -> (lr mapRight (_ tail)))
def splitAt(index: Index): Split[A] = Split(xs take index.sizeExcluding, xs drop index.sizeExcluding)
def sum(implicit z: AdditiveMonoid[A]): A = z sum xs.trav
def transpose[B](implicit ev: A <:< View[B]): View2D[B] = indices.all map (n => xs flatMap (_ drop n.sizeExcluding take 1))
def zreducel(f: BinOp[A])(implicit z: Empty[A]): A = if (isEmpty) z.empty else reducel(f)
def zreducer(f: BinOp[A])(implicit z: Empty[A]): A = if (isEmpty) z.empty else reducer(f)
/** This is kind of horrific but has the advantage of not being as busted.
* We need to not be using scala's map because it will always compare keys based
* on the inherited equals.
*/
def groupBy[B: Eq](f: A => B): ExMap[B, View[A]] = {
var seen: Vec[B] = vec()
val buf = bufferMap[Index, Vec[A]]()
xs foreach { x =>
val fx: B = f(x)
val idx: Index = seen.m indexOf fx match {
case NoIndex => seen = seen :+ fx ; seen.lastIndex
case idx => idx
}
buf(idx) :+= x
}
val res = buf.toMap map { case (k, v) => seen(k) -> v.m }
res.m.toMap[ExMap]
}
def mpartition(p: View[A] => ToBool[A]): View2D[A] = (
inView[View[A]](mf => xs.toEach partition p(memo) match {
case Split(xs, ys) =>
mf(xs)
ys mpartition p foreach mf
})
)
def distinctBy[B: Eq](f: A => B): View[A] = inView { mf =>
zfoldl[ExSet[B]] { (seen, x) =>
val y = f(x)
if (seen(y)) seen else {
mf(x)
seen + y
}
}
}
private[this] def orderOps(z: Order[A]): HasOrder[A] = new HasOrder[A](xs)(z)
}
final class View2DOps[A](val xss: View2D[A]) {
def flatten: View[A] = xss flatMap identity
def mmap[B](f: A => B): View2D[B] = xss map (_ map f)
}
/** Methods requiring us to have additional knowledge, by parameter or type class.
* We keep the interface simple and foolproof by establishing thet instance
* first and only offering the methods after that.
*
* But.
*
* This approach, so nice in principle, stretches scala's willingness to connect
* implicits past its abilities. It works on psp collections, but when we depend on
* an implicit to entire Viewville in the first place, then these methods become
* out of reach without an implicit call to .m to become a view.
*
* The search continues.
*/
class HasEq[A](xs: View[A])(implicit z: Eq[A]) {
def contains(x: A): Boolean = xs exists (_ === x)
def distinct: View[A] = xs.zfoldl[Vec[A]]((res, x) => if (res.m contains x) res else res :+ x)
def indexOf(x: A): Index = xs indexWhere (_ === x)
def indicesOf(x: A): View[Index] = xs indicesWhere (_ === x)
def mapOnto[B](f: A => B): ExMap[A, B] = toSet mapOnto f
def toBag: Bag[A] = xs groupBy identity map (_.size.getInt)
def toSet: ExSet[A] = xs.toExSet
def without(x: A): View[A] = xs filterNot (_ === x)
def withoutEmpty(implicit z: Empty[A]): View[A] = this without z.empty
}
class HasHash[A](xs: View[A])(implicit z: Hash[A]) extends HasEq[A](xs)(z) {
override def toSet: ExSet[A] = xs.toHashSet
}
final class HasOrder[A](xs: View[A])(implicit z: Order[A]) extends HasEq[A](xs) {
def max: A = xs reducel (_ max _)
def min: A = xs reducel (_ min _)
def sorted: View[A] = xs.toRefArray.inPlace.sort
}
final class HasEmpty[A](xs: View[A])(implicit z: Empty[A]) {
def zfind(p: ToBool[A]): A = xs.findOr(p, emptyValue)
def zhead: A = xs take 1 zfoldl ((zero: A, head: A) => head)
}
final class HasInitialValue[+A, B](xs: View[A], initial: B) {
def indexed(f: (B, A, Index) => B): B = lowlevel.ll.foldLeftIndexed(xs, initial, f)
def left(f: (B, A) => B): B = lowlevel.ll.foldLeft(xs, initial, f)
def right(f: (A, B) => B): B = lowlevel.ll.foldRight(xs, initial, f)
}
final class WithIndex[+A](xs: View[A]) {
def fold[@fspec B](zero: B)(f: (B, A, Index) => B): B = xs.foldFrom(zero) indexed f
def foreach(f: (A, Index) => Unit): Unit = lowlevel.ll.foldLeftIndexed[A, Unit](xs, (), (acc, x, i) => f(x, i))
def map[B](f: Index => A => B): View[B] = zipped map ((x, i) => f(i)(x))
def mapZip[B](f: Index => A => B): ZipView[A, B] = Zip.zipf(xs)(f)
def zipped: ZipView[A, Index] = xs zip indices.all
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy