Skip to content

Instantly share code, notes, and snippets.

@etorreborre
Created August 4, 2010 00:10
Show Gist options
  • Save etorreborre/507424 to your computer and use it in GitHub Desktop.
Save etorreborre/507424 to your computer and use it in GitHub Desktop.
/*
This fails to compile with:
type mismatch;
found : Iterable[T]
required: CC[T]
else if (predicate(xs.head)) xs.drop(1)
^
type mismatch;
found : Iterable[T]
required: CC[T]
else xs.take(1) ++ xs.tail.removeFirst(predicate)
*/
object o {
implicit def extendedIterable[T, CC[T] <: Iterable[T]](xs: CC[T]) = new ExtendedIterable(xs)
class ExtendedIterable[T, CC[T] <: Iterable[T]](xs: CC[T]) {
def removeFirst(predicate: T => Boolean): CC[T] = {
if (xs.isEmpty) xs
else if (predicate(xs.head)) xs.drop(1)
else xs.take(1) ++ xs.tail.removeFirst(predicate)
}
}
val l: List[Int] = List(1, 2).removeFirst((i: Int) => i > 0)
println(l)
}
@inkytonik
Copy link

Erg. Sorry about that copy and paste problem. I'll stop now...

@inkytonik
Copy link

import collection.generic.CanBuildFrom
import collection.IterableLike
import collection.immutable.BitSet
import collection.immutable.Queue

trait IterableRemovals0 {

    // Must be in base class since it clashes with extendedIterable1 for types such as List or Set
    // This makes extendedIterable1 take priority, but we get this one for types such as BitSet

    implicit def extendedIterable0[CC <: IterableLike[Int, CC]](xs: CC) = new ExtendedIterable0[CC](xs)
    class ExtendedIterable0[CC <: IterableLike[Int, CC]](xs: CC)  {
      def removeFirst(predicate: Int => Boolean)(implicit cbf: CanBuildFrom[CC, Int, CC]): CC = {
        if (xs.isEmpty) xs
        else if (predicate(xs.head)) xs.drop(1)
        else xs.take(1) ++ xs.tail.removeFirst(predicate)
      }
    }

    // This one doesn't compile for some reason
    //
    // implicit def extendedIterable0[T, CC <: IterableLike[T, CC]](xs: CC) = new ExtendedIterable0[T, CC](xs)
    // class ExtendedIterable0[T, CC <: IterableLike[T, CC]](xs: CC)  {
    //   def removeFirst(predicate: T => Boolean)(implicit cbf: CanBuildFrom[CC, T, CC]): CC = {
    //     if (xs.isEmpty) xs
    //     else if (predicate(xs.head)) xs.drop(1)
    //     else xs.take(1) ++ xs.tail.removeFirst(predicate)
    //   }
    // }

}

trait IterableRemovals extends IterableRemovals0 {

    implicit def extendedIterable1[T, CC[T] <: IterableLike[T, CC[T]]](xs: CC[T]) = new ExtendedIterable1[T, CC](xs)
    class ExtendedIterable1[T, CC[T] <: IterableLike[T, CC[T]]](xs: CC[T])  {
      def removeFirst(predicate: T => Boolean)(implicit cbf: CanBuildFrom[CC[T], T, CC[T]]): CC[T] = {
        if (xs.isEmpty) xs
        else if (predicate(xs.head)) xs.drop(1)
        else xs.take(1) ++ xs.tail.removeFirst(predicate)
      }
    }

    implicit def extendedIterable2[T, U, CC[T,U] <: IterableLike[(T,U), CC[T,U]]](xs: CC[T,U]) = new ExtendedIterable2[T, U, CC](xs)
    class ExtendedIterable2[T, U, CC[T,U] <: IterableLike[(T,U), CC[T,U]]](xs: CC[T,U])  {
      def removeFirst(predicate: ((T,U)) => Boolean)(implicit cbf: CanBuildFrom[CC[T,U], (T,U), CC[T,U]]): CC[T,U] = {
        if (xs.isEmpty) xs
        else if (predicate(xs.head)) xs.drop(1)
        else xs.take(1) ++ xs.tail.removeFirst(predicate)
      }
    }

}

object Eric extends Application with IterableRemovals {

  val l: List[Int] = List(1, 2).removeFirst((i: Int) => i > 0)
  println(l)
  val l2: List[String] = List("1", "2").removeFirst((s: String) => s.toInt > 0)
  println(l2)
  val s: Set[Int] = Set(1, 2).removeFirst((i: Int) => i > 0)
  println(s)
  val s2: Set[String] = Set("1", "2").removeFirst((s: String) => s.toInt > 0)
  println(s2)
  val b: BitSet = BitSet(1, 2).removeFirst((i: Int) => i > 0)
  println(b)
  val q: Queue[Int] = Queue(1, 2).removeFirst((i: Int) => i > 0)
  println(q)
  val q2: Queue[String] = Queue("1", "2").removeFirst((s: String) => s.toInt > 0)
  println(q2)
  val m: Map[Int,Int] = Map(1 -> 8, 2 -> 9).removeFirst{ case (x,y) => x > 0 }
  println(m)
  val m2: Map[String,Int] = Map("1" -> 8, "2" -> 9).removeFirst{ case (x,y) => x.toInt > 0 }
  println(m2)

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment