diff --git a/Scala/.gitignore b/Scala/.gitignore new file mode 100644 index 0000000..b4a5277 --- /dev/null +++ b/Scala/.gitignore @@ -0,0 +1,3 @@ +.idea/ +target/ +*.iml diff --git a/Scala/1-callback.scala b/Scala/1-callback.scala new file mode 100644 index 0000000..92fba0d --- /dev/null +++ b/Scala/1-callback.scala @@ -0,0 +1,24 @@ +object Callback { + + def func(data: Option[String], callback: (Either[Exception, String]) => Int): Int = + data map {d => + callback(Right(s"Data: $d")) + } getOrElse { + callback(Left(new Exception("Exception occurred!"))) + } + + def simpleCallback(input: Either[Exception, String]): Int = + input map { s: String => + println(s) + 1 // ok, status 1 + } getOrElse { + println(s"Data is not present!\n${input.left.get.getMessage}") + -1 // NOT ok, status -1 + } + + def main(args: Array[String]): Unit = { + println(s"None status = ${func(None, simpleCallback)}") + + println(s"Some status = ${func(Some("123"), simpleCallback)}") + } +} diff --git a/Scala/2-closure.scala b/Scala/2-closure.scala new file mode 100644 index 0000000..b4457b7 --- /dev/null +++ b/Scala/2-closure.scala @@ -0,0 +1,16 @@ +object Closure { + def func(a: String): String => Unit = { + val b = "Closure variable" + + (c: String) => + println(s"$a\t$b\t$c") + } + + def main(args: Array[String]): Unit = { + val f1 = func("Number 1") + f1("Number 2") + + val f2 = func("Parameter X") + f2("Parameter Y") + } +} diff --git a/Scala/3-chain.scala b/Scala/3-chain.scala new file mode 100644 index 0000000..b9964fb --- /dev/null +++ b/Scala/3-chain.scala @@ -0,0 +1,15 @@ +object Chain { + + def sum(a: Int) = + (b: Int) => + (c: Int) => + a + b + c + + def main(args: Array[String]): Unit = { + val f1 = sum(1)(1) + val s1 = f1(1) + val s2 = f1(2) + + println(s"$s1\t$s2") + } +} diff --git a/Scala/4-cache.scala b/Scala/4-cache.scala new file mode 100644 index 0000000..0c50c56 --- /dev/null +++ b/Scala/4-cache.scala @@ -0,0 +1,32 @@ +object Cache { + + def cached() = { + println("Generate cache") + var cache: Int Map String = Map.empty[Int, String] + + (a: Int) => + cache.get(a) map { value => + println("Found in cache") + value + } getOrElse { + println("Not found in cache, calculating and saving") + val res = a -> s"value $a" + cache += res + res + } + } + + def main(args: Array[String]): Unit = { + val f1 = cached() + f1(1) + f1(2) + f1(1) + f1(2) + + val f2 = cached() + f2(1) + f2(2) + f2(1) + f2(2) + } +} diff --git a/Scala/5-complex.scala b/Scala/5-complex.scala new file mode 100644 index 0000000..2c4c0d8 --- /dev/null +++ b/Scala/5-complex.scala @@ -0,0 +1,75 @@ +/** + * Some more complex examples of higher order functions usage + * there are `sum` and `product` functions with regular and tail recursive examples + * and some generalized functions which can be used for creating `sum` and `product` + */ + +object ComplexExample { + + def sum(f: (Int) => Int)(a: Int, b: Int): Int = + if (a > b) 0 + else f(a) + sum(f)(a + 1, b) + + + def product(f: (Int) => Int)(a: Int, b: Int): Int = + if (a > b) 1 + else f(a) * product(f)(a + 1, b) + +// tail recursive sum + def sum1(f: (Int) => Int)(a: Int, b: Int): Int = { + def loop(buf: Int)(curr: Int): Int = + if (curr > b) buf + else loop(buf + f(curr))(curr + 1) + + loop(0)(a) + } + +// tail recursive product + def product1(f: (Int) => Int)(a: Int, b: Int): Int = { + def loop(buf: Int)(curr: Int): Int = + if (curr > b) buf + else loop(buf * f(curr))(curr + 1) + + loop(1)(a) + } + + def generalized(zero: Int)(combine: (Int, Int) => Int): (Int => Int) => (Int, Int) => Int = { + def innerFunc(f: (Int) => Int)(a: Int, b: Int): Int = { + if (a > b) zero + else combine(f(a), innerFunc(f)(a + 1, b)) + } + innerFunc + } + +// tail recursive generalized function + def generalized1(zero: Int)(combine: (Int, Int) => Int): (Int => Int) => (Int, Int) => Int = { + (f: (Int) => Int) => (a: Int, b: Int) => { + def loop(buf: Int)(curr: Int): Int = + if (curr > b) buf + else loop(combine(buf, f(curr)))(curr + 1) + + loop(zero)(a) + } + } + + def main(args: Array[String]): Unit = { + val identity = (x: Int) => x + val square = (x: Int) => x * x + + val generalizedSum = generalized(0)(_ + _) + val generalizedSum1 = generalized1(0)(_ + _) + println("sum of squares") + println(s"sum(x => x * x)(1, 5) = ${sum(square)(1, 5)}") + println(s"sum1(x => x * x)(1, 5) = ${sum1(square)(1, 5)}") + println(s"generalizedSum(x => x * x)(1, 5) = ${generalizedSum(square)(1, 5)}") + println(s"generalizedSum1(x => x * x)(1, 5) = ${generalizedSum1(square)(1, 5)}") + + val generalizedProduct = generalized(1)(_ * _) + val generalizedProduct1 = generalized1(1)(_ * _) + println("factorial") + println(s"product(x => x)(1, 5) = ${product(identity)(1, 5)}") + println(s"product1(x => x)(1, 5) = ${product1(identity)(1, 5)}") + println(s"generalizedProduct(x => x)(1, 5) = ${generalizedProduct(identity)(1, 5)}") + println(s"generalizedProduct1(x => x)(1, 5) = ${generalizedProduct1(identity)(1, 5)}") + } +}