Skip to content

Instantly share code, notes, and snippets.

@Vilkina
Created May 26, 2020 11:42
Show Gist options
  • Save Vilkina/093679312c49c349557abf92ae5e3f86 to your computer and use it in GitHub Desktop.
Save Vilkina/093679312c49c349557abf92ae5e3f86 to your computer and use it in GitHub Desktop.
package repeat
abstract class MyList[+A] {
def head: A
def tail: MyList[A]
def isEmpty: Boolean
def add[B >: A](element: B): MyList[B]
def printElements: String
override def toString: String = "[" + printElements + "]"
def map[B](transformer: MyTransformer[A, B]): MyList[B]
def flatMap[B](transformer: MyTransformer[A, MyList[B]]): MyList[B]
def filter(predicate: MyPredicate[A]): MyList[A]
def ++[B >: A](list: MyList[B]): MyList[B]
def foreach(f: A => Unit): Unit
def sort(compare: (A, A) => Int): MyList[A]
def zipWith[B, C](list: MyList[B], zip: (A, B) => C): MyList[C]
def fold[B](start: B)(operator: (B, A) => B): B
}
case object Empty extends MyList[Nothing] {
def head: Nothing = throw new NoSuchElementException
def tail: MyList[Nothing] = throw new NoSuchElementException
def isEmpty: Boolean = true
def add[B >: Nothing](element: B): MyList[B] = new Cons(element, Empty)
def printElements: String = ""
def map[B](transformer: MyTransformer[Nothing, B]): MyList[B] = Empty
def flatMap[B](transformer: MyTransformer[Nothing, MyList[B]]): MyList[B] = Empty
def filter(predicate: MyPredicate[Nothing]): MyList[Nothing] = Empty
def ++[B >: Nothing](list: MyList[B]): MyList[B] = list
//hofs
def foreach(f: Nothing => Unit): Unit = ()
def sort(compare: (Nothing, Nothing) => Int) = Empty
def zipWith[B, C](list: MyList[B], zip: (Nothing, B) => C): MyList[C] =
if(!list.isEmpty) throw new RuntimeException("Lists do not have the same len")
else Empty
def fold[B](start: B)(operator: (B, Nothing) => B): B = start
}
case class Cons[+A](h: A, t: MyList[A]) extends MyList[A] {
def head: A = h
def tail: MyList[A] = t
def isEmpty: Boolean = false
def add[B >: A](element: B): MyList[B] = new Cons(element, this)
def printElements: String =
if (t.isEmpty) "" + h
else h + " " + t.printElements
def map[B](transformer: MyTransformer[A, B]): MyList[B] = new Cons(transformer.transform(h), t.map(transformer))
def flatMap[B](transformer: MyTransformer[A, MyList[B]]): MyList[B] =
transformer.transform(h) ++ t.flatMap(transformer)
def filter(predicate: MyPredicate[A]): MyList[A] =
if (predicate.test(h)) new Cons(h, t.filter(predicate))
else t.filter(predicate)
def ++[B >: A](list: MyList[B]): MyList[B] = new Cons(h, t ++ list)
def foreach(f: A => Unit): Unit = {
f(h)
t.foreach(f)
}
def sort(compare: (A, A) => Int): MyList[A] = {
def insert(x: A, sortedList: MyList[A]): MyList[A] =
if (sortedList.isEmpty) new Cons(x, Empty)
else if (compare(x, sortedList.head) <= 0) new Cons(x, sortedList)
else new Cons(sortedList.head, insert(x, sortedList.tail))
val sortedTail = t.sort(compare)
insert(h, sortedTail)
}
def zipWith[B, C](list: MyList[B], zip: (A, B) => C): MyList[C] =
if(list.isEmpty) throw new RuntimeException("Lists do not have the same len")
else new Cons(zip(h, list.head), t.zipWith(list.tail, zip))
def fold[B](start: B)(operator: (B, A) => B): B = {
val newStart = operator(start, h)
t.fold(newStart)(operator)
}
}
trait MyPredicate[-T] {
def test(elem: T ): Boolean
}
trait MyTransformer[-A, B] {
def transform(elem: A): B
}
object ListTest extends App {
val listOfIntegers: MyList[Int] = new Cons(1, new Cons(2, new Cons(3, Empty)))
val cloneListOfIntegers: MyList[Int] = new Cons(1, new Cons(2, new Cons(3, Empty)))
val listOfStrings: MyList[String] = new Cons("Hello", new Cons("Scala", Empty))
//println(listOfIntegers.toString)
//println(listOfStrings.toString)
// println(listOfIntegers.map(_ * 2).toString)
// println(listOfIntegers.map(_ % 2 == 0).toString)
//listOfIntegers.foreach(println)
val combination = for {
n <- listOfIntegers
string <- listOfStrings
} yield n + "-" + string
println(combination)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment