===== Lecture 03. Higher-order functions ===== /* def sumAll(start: Int, stop: Int): Int = { def loop (i: Int, acc: Int): Int = if (i > stop) acc else loop(i+1, i + acc) loop(start,0) } def sumSquares(start: Int, stop: Int): Int = { def loop (i: Int, acc: Int): Int = if (i > stop) acc else loop(i+1, i*i + acc) loop(start,0) }*/ def sumWithF(f: Int => Int, start:Int, stop:Int): Int = { def loop (i: Int, acc: Int): Int = if (i > stop) acc else loop(i+1, f(i) + acc) loop(start,0) } def id(x: Int): Int = x def square(x: Int): Int = x * x sumWithF(id,0,10) sumWithF(square,0, 10) sumWithF((x: Int) => x, 0, 10) sumWithF(x => x, 0, 10) sumWithF(x => x * x, 0, 10) val func: (Int,Int) => Int = (x: Int, y: Int) => x + y val func2: (Int,Int) => Int = (x,y) => x + y /* Sa ne imaginam urmatorul scenariu: Avem un range extrem de mare de valori int, Vrem sa aplicam cativa algoritmi, pe foarte multe range-uri diferite. Algoritmii sunt putini (3), range-urile sunt foarte multe. */ sumWithF(x => x, 0, 10) sumWithF(x => x * x, 10, 20) def alg1(x: Int): Int = x def alg2(x: Int): Int = x * x def alg3(x: Int): Int = x * x * x def currySumWithF(f: Int => Int): (Int, Int) => Int = { def sumWithF(start: Int, stop: Int): Int = { def loop(i: Int, acc: Int): Int = if (i > stop) acc else loop(i+1,f(i) + acc) loop(start,0) } sumWithF } def cleanSumWithF(f: Int => Int)(start: Int, stop: Int): Int = { def loop(i: Int, acc: Int): Int = if (i > stop) acc else loop(i+1, f(i) + acc) loop(start,0) } val applyAlg1:(Int, Int) => Int = cleanSumWithF(alg1) val applyAlg2:(Int, Int) => Int = cleanSumWithF(alg2) applyAlg1(0,10) applyAlg2(0,10) cleanSumWithF(x => x * x)(0,10) val test: (Int, Int) => Int = cleanSumWithF(x => x * x) test(0,10) //primeste parametrii "pe rand" = // functia este in forma curry def f(x: Int)(y: Int)(z: Int): Int = x + y + z val func3: Int => Int => Int = f(1) f(1)(2)(3) def g(x: Int, y: Int, z: Int): Int = x + y + z g(1,2,3) // cum procedam daca vrem sa compunem algoritmi? //def compose(f: Int => Int, g: Int => Int): Int => Int = // x => f(g(x)) type Algorithm = Int => Int def compose(f: Algorithm, g: Algorithm): Algorithm = x => f(g(x)) cleanSumWithF(compose(alg1,alg2))(0,10) /* Sa presupunem ca vrem sa definim functii 2D y = ax + b */ type Fun2D = Int => Int val ff: Int => Int = x => 2*x + 1 // in forma curry def gen2DFun (a: Int)(b: Int): Fun2D = x => a*x + b val fff = gen2DFun(2)(1) def uncurry (gen: Int => Int => Fun2D): (Int,Int) => Fun2D = (x,y) => gen(x)(y)