Skip to content

Instantly share code, notes, and snippets.

@jaymody
Created November 23, 2021 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaymody/82f0bf12a9a5efaa2282dfe429db9bed to your computer and use it in GitHub Desktop.
Save jaymody/82f0bf12a9a5efaa2282dfe429db9bed to your computer and use it in GitHub Desktop.
Recursive, functional re-implementation of iterable functions (map, reduce, groupBy, etc ...) in Scala.
case class MyList[A](l: Seq[A]) {
def filter(f: A => Boolean): Seq[A] = l match {
case Nil => l
case x :: xs if !f(x) => xs.filter(f)
case x :: xs if f(x) => x +: xs.filter(f)
}
def map[B](f: A => B): Seq[B] = l match {
case Nil => Nil
case x :: xs => f(x) +: xs.map(f)
}
def groupBy[K](f: A => K): Map[K, Seq[A]] = {
def gby(l: Seq[A], m: Map[K, Seq[A]])(implicit f: A => K): Map[K, Seq[A]] =
l match {
case Nil => m
case x :: xs if m.contains(f(x)) =>
gby(xs, m + (f(x) -> (m(f(x)) :+ x)))
case x :: xs if !m.contains(f(x)) => gby(xs, m + (f(x) -> Seq(x)))
}
gby(l, Map())(f)
}
def foldLeft[B](z: B)(f: (B, A) => B): B = l match {
case Nil => z
case x :: xs => xs.foldLeft(f(z, x))(f)
}
def reduce(f: (A, A) => A): A = l match {
case Nil => throw new IllegalArgumentException("List must not be empty")
case x :: xs => xs.foldLeft(x)(f)
}
def forall(p: A => Boolean): Boolean = l match {
case Nil => true
case x :: xs => p(x) && xs.forall(p)
}
def foreach(f: A => Unit): Unit = l match {
case x :: xs => { f(x); xs.foreach(f) }
}
def count(p: A => Boolean): Int = l match {
case Nil => 0
case x :: xs => xs.count(p) + { if (p(x)) 1 else 0 }
}
def partition(p: A => Boolean): (Seq[A], Seq[A]) = {
val part = l.groupBy(p)
(part(true), part(false))
}
// TODO: def flatten
// TODO: def fold
// TODO: def foldRight
// TODO: def corresponds
// TODO: def indexOf
// TODO: def intersect
// TODO: def diff
// TODO: def distinct
// TODO: def drop
// TODO: def dropRight
// TODO: def combinations
// TODO: def collect
// TODO: def flatMap
// TODO: def permutations
// TODO: def union
}
object Collections {
def test[A](a: A, b: A): Unit = {
println(a == b)
println(a)
println(b)
println()
}
def main(args: Array[String]): Unit = {
val list = (1 to 10).toList
val myList = MyList(list)
println("--- test map ---")
val f1 = (x: Int) => x * 2
test(myList.map(f1), list.map(f1))
println("--- test filter ---")
val f2 = (x: Int) => x % 2 == 0
test(myList.filter(f2), list.filter(f2))
println("--- test groupBy ---")
val f3 = (x: Int) => x % 3
test(myList.groupBy(f3), list.groupBy(f3))
println("--- test foldLeft ---")
val f4 = (x: Int, y: Int) => x + y
test(myList.foldLeft(0)(f4), list.foldLeft(0)(f4))
println("--- test reduce ---")
val f5 = (x: Int, y: Int) => x + y
test(myList.reduce(f5), list.reduce(f5))
println("--- test partition ---")
val f6 = (x: Int) => x % 2 == 0
test(myList.partition(f6), list.partition(f6))
println("--- test foreach ---")
val f7 = (x: Int) => print(s"$x -> ")
myList.foreach(f7)
println()
list.foreach(f7)
println()
println()
println("--- test forall ---")
val f8 = (x: Int) => x < 100
test(myList.forall(f8), list.forall(f8))
val f9 = (x: Int) => x > 5
test(myList.forall(f9), list.forall(f9))
println("--- test count ---")
val f10 = (x: Int) => x % 2 == 0
test(myList.count(f10), list.count(f10))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment