In this example, we are going to examine the function and closures and here is the outline.
1. Function
1.1. one thing about Scala is that
1.2 first class function
1.3 function can be short-forms
1.4 placeholder syntax
2. closure
2.1. closure in simple form
3. function call in special form
3.1 repeated parameters
3.2 Default parameter values
4. tail recursion
4.1 an interest note on the tail-recursion limit
// function_closures.scala // scala functions and closures in example // 1. Function // // 1.1. one thing about Scala is that // one strong suite about scala is that you can define local function for Scala import scala.io.Source object LongLines { def processFile(fileName : String, width : Int) = { // local function def processLine(line : String) = { if (line.length > width) println(fileName + ": " + line) } for (line <- Source.fromFile(fileName).getLines) processLine(line) } } // runner LongLines.processFile("C:\\dev\\workspace\\scala-train\\src\\functionsAndClosures\\function_closures.scala", 6) // 1.2 first class function // function as the first class type means // 1). you can create a function literal, which when is compiled into a class that when instantiated at runtime is a function value // 2). you can pass around the function value around (x :Int) => x + 1 var increase = (x :Int) => x + 1 val someNumbers = List(-11, -10, -5, 0, 5, 10) someNumbers.foreach((x :Int) => println(x)) // 1.3 function can be short-forms // longer form someNumbers.filter((x :Int) => x > 0) // short form someNumbers.filter(x => x > 0) //1.4 placeholder syntax // why do we need 'x', since we barely need that variable name, we can ignore the // 'x' and the parameter part , and just use following functional body literal someNumbers.filter(_ > 0) val f = ( _ : Int) + (_ : Int) f(5, 10) //1.4 partially function def sum(a :Int, b : Int, c :Int) = a + b + c // you can use '_' to create a partially apply function by which you supply none of the required arguments val a = sum _ a (1 ,2, 3 ) // above is interchanable to the following a.apply(1, 2, 3) val b = sum (1, _ :Int, 3) b(2) someNumbers.foreach(println _) // if you are writing a partially function in which you leave off all the parameters, such as println _, or sum _, you can express more concisely by leaving // off the underscore if a function is required at that point in the code someNumbers.foreach(println) //NOTE: you cannot do that if data is required... //2. closure // closure is the abilty from within a scope (a local functional literal) which refers to some free local variable, and because of that // the lifetime of the freevar has been extended with the local/anonymous function // 2.1. closure in simple form var more = 1 val addMore = (x : Int) => x + more addMore(1) more = 9999 addMore(10) // def makeIncreaser(more : Int) = (x: Int) => x + more val increaser1 = makeIncreaser(1) val increaser2 = makeIncreaser(2) // each time makeIncreaser is called, a new closure is created increaser1 == increaser2 // 3. function call in special form // 3.1 repeated parameters def echo(args : String*) = for (arg <- args) println(arg) echo() echo("one") // actually Array[String] will be passed in to the function below echo("hello", "world") // how do we unpack a array, list and pass that as repeated parameters? // the key lies in "_*" val arr = Array("what's", "is", "up") echo(arr : _*) // 3.2 Default parameter values // you can pass in default parameter values def printTime(out : java.io.PrintStream = Console.out) = out.println("Time = " + System.currentTimeMillis()) // you can call function with default argument values // with the named arguments (which is called keyword argument in Python) def printTime2(out : java.io.PrintStream = Console.out, divisor: Int = 1) = out.println("Time = " + System.currentTimeMillis() / divisor) printTime2(divisor = 2) // 3. tail recursion // tail recursion is an optimization that is performed by the compiler, it just jump back to the beginning of the function // with parameter values replaced.. // a non-tail recursive function def boom(x :Int) : Int = if (x == 0) throw new Exception("boom!") else boom(x - 1 ) + 1 // check the stack boom(2) // a tail recursive one def boom(x :Int) : Int = if (x == 0) throw new Exception("boom!") else boom(x - 1 ) boom(10) // 3.1 an interest note on the tail-recursion limit // // this do not do tail-recursion def isEven(x : Int) : Boolean = if (x == 0) true else isOdd(x - 1) def isOdd(x : Int) : Boolean = if (x == 0) false else isEven(x - 1) isEven(9) val funValue = nestedFun _ def nestedFun (x : Int) { if (x != 0) { println(x); funValue(x - 1)} } funValue(3)