a a’s
v v’s
a a’s 2.5
das dsa
scala> def loop() = loop //infinite loop OR def loop: Boolean = loop Call by value [only evaluate once] - Call by Name [arg not evaluated if not used] scala> def test(x:Int, y: Int) = x scala> test(3+4, 8)
def func(x:Int, y: => Int) = x + y //y is call by name because of => func(1+2, loop) 1+2 3 func(loop, 1+2) //infinite If is a statement not an expression scala> def abs(x: Int) = if (x > 0) x else -x def is call by name, function body will not be evaluated until called. but val is call by value and the function is evaluated right there.def x = loop //OK val x = loop //INFINITE LOOP implement && function: def and(x: Boolean, y: => Boolean) = if (x) y else false //=> let's us have short circuiting and in case x is false we won't go to evaluate y. and(false, loop) // if y is not call by name we will stick to infinite loop otherwise it evaluates to false. Blocks {}is an expression itself. sequence of expressions, the last expression is the value of the block Semicolons are optional. when writing expressions in multiple lines scala assumes they are differnet expressions but we only want to have them in multiple lines. To avoid use parenthesis, OR write operator as character on previous line
nesting functions you can inherit variables instead of sending them as explicit parameters. Tail RecursionIn a tail recursive function, all calculations happen first and the recursive call is the last thing that happens. functions that take other functions as parameters or that return functions as results are called higher order functionsImagine a tail recursive function. It runs. It completes all its computation. As its very last action, it is ready to make its recursive call. What, at this point, is the use of the stack frame? None at all. We don’t need our local variables anymore because we’re done with all computations. We don’t need to know which function we’re in because we’re just going to re-enter the very same function. Scala, in the case of tail recursion, can eliminate the creation of a new stack frame and just re-use the current stack frame. The stack never gets any deeper, no matter how many times the recursive call is made. That’s the voodoo that makes tail recursion special in scala. Incidentally, some languages achieve a similar end by converting tail recursion into iteration rather than by manipulating the stack. This won’t work with head recursion. Do you see why? Imagine a head recursive function. First it does some work, then it makes its recursive call, then it does a little more work. We can’t just re-use the current stack frame when we make that recursive call. We’re going to NEED that stack frame info after the recursive call completes. It has our local variables, including the result (if any) returned by the recursive call. def listLength2( list : List [_]): Int = { def listLength2Helper( list : List [_], len : Int ): Int = { if ( list = = Nil) len else listLength2Helper( list .tail, len + 1 ) } listLength2Helper( list , 0 ) } println( listLength2( list1 ) ) println( listLength2( list2 ) ) this function first checks for a Nil list, but this time returns the len
parameter rather than 0. If list is non-Nil then we make the recursive
call. But there’s still an addition going on here, len + 1. Does that
ruin the tail recursion? No. That term is evaluated first. Only
after all the parameters have been evaluated does the recursive call
happen. This function does indeed qualify for tail recursion
optimization. ONLY ONE STACK IS ENOUGH!!! each time it is replaced/swapped with the last call. because that is what is returned.This is not tail recursive: def listLength1( list : List [_]): Int = { if ( list = = Nil) 0 else 1 + listLength1( list .tail) } def factorial(n : BigInt) : BigInt = { if (n == 0 ) 1 else n*factorial(n- 1 ) } @tailrec //tell scala to tail recursive it factorial(n : BigInt) : BigInt = { def loop(n : BigInt, acc : BigInt) : BigInt = if (n < = 0 ) acc else loop(n- 1 ,acc*n) loop(n, 1 ) } function as an argument sum(f: Int => Int, x: Int, y: Int) : Int = if (x<=y) f(x) + sum(x + 1, y) else 0 //sigma f(i) i from x to y def sumcube(a: Int, b: Int) = sum(x => x * x * x, a, b) //the type can be omitted if it can be inferred from context anonymous (x:Int, y:Int) => x+y |