← Scala EnglishChapter 05 of 13

Functions

## Learning Objectives - Master function definitions with def - Understand function parameters and return types - Learn recursion - Work with anonymous functions - Understand closures and partial applications ## Function Basics ### Defining Functions ```scala def greet(): String = { "Hello, World!" } println(greet()) // Hello, World! ``` ### Function with Parameters ```scala def add(a: Int, b: Int): Int = { a + b } println(add(3, 5)) // 8 ``` ### Return Type Inference Scala can infer return types for expressions: ```scala def add(a: Int, b: Int) = a + b // Return type inferred as Int def greet() = "Hello" // Return type inferred as String ``` ### Unit Return Type ```scala def printSum(a: Int, b: Int): Unit = { println(s"Sum: ${a + b}") } printSum(3, 5) // Sum: 8 ``` ## Parameter Types ### Default Parameters ```scala def greet(name: String = "World") = s"Hello, $name!" greet() // Hello, World! greet("Alice") // Hello, Alice! ``` ### Named Arguments ```scala def connect(host: String = "localhost", port: Int = 8080) = { s"$host:$port" } connect(port = 9000, host = "server") // server:9000 ``` ### Variable Arguments (Varargs) ```scala def sum(numbers: Int*): Int = { numbers.sum } sum(1, 2, 3, 4, 5) // 15 sum(1, 2, 3) // 6 ``` ### Parameter Groups ```scala def addAndMultiply(a: Int)(b: Int)(c: Int): Int = { (a + b) * c } addAndMultiply(1)(2)(3) // 9 ``` ## Recursion ### Basic Recursion ```scala def factorial(n: Int): BigInt = { if (n <= 1) 1 else n * factorial(n - 1) } factorial(5) // 120 ``` ### Tail Recursion Tail-recursive functions are optimized to avoid stack overflow: ```scala def factorialTail(n: Int): BigInt = { @annotation.tailrec def loop(acc: BigInt, n: Int): BigInt = { if (n <= 1) acc else loop(acc * n, n - 1) } loop(1, n) } factorialTail(10000) // Works without stack overflow ``` ### Mutual Recursion ```scala def isEven(n: Int): Boolean = if (n == 0) true else isOdd(n - 1) def isOdd(n: Int): Boolean = if (n == 0) false else isEven(n - 1) isEven(10) // true ``` ## Anonymous Functions ### Basic Syntax ```scala val addOne = (x: Int) => x + 1 addOne(5) // 6 ``` ### Multiple Parameters ```scala val add = (a: Int, b: Int) => a + b add(3, 5) // 8 ``` ### No Parameters ```scala val getTime = () => System.currentTimeMillis() getTime() ``` ### Placeholder Syntax ```scala val numbers = List(1, 2, 3, 4, 5) numbers.map((x: Int) => x * 2) numbers.map(x => x * 2) numbers.map(_ * 2) // Placeholder for single parameter val add = (_: Int) + (_: Int) // Multiple placeholders add(3, 5) // 8 ``` ## Higher-Order Functions Functions that take functions as parameters or return functions: ```scala def applyTwice(f: Int => Int, x: Int): Int = { f(f(x)) } def double(x: Int) = x * 2 applyTwice(double, 5) // 20 (5 * 2 * 2) ``` ### Functions as Return Values ```scala def multiplier(factor: Int): Int => Int = { (x: Int) => x * factor } val triple = multiplier(3) triple(5) // 15 ``` ## Closures A closure is a function that captures variables from its enclosing scope: ```scala var factor = 10 val multiply: Int => Int = (x: Int) => x * factor multiply(5) // 50 factor = 20 multiply(5) // 100 (closure sees new value) ``` ## Currying ### Curried Functions ```scala def curriedSum(a: Int)(b: Int): Int = a + b curriedSum(3)(5) // 8 val addFive = curriedSum(5) _ addFive(3) // 8 ``` ### Why Currying? ```scala def withTimestamp(log: String => Unit)(message: String): String = { val timestamp = System.currentTimeMillis() log(s"[$timestamp] $message") message } def logToConsole(msg: String) = println(msg) def logToFile(msg: String) = /* write to file */ () val timestampedLog = withTimestamp(logToConsole) _ timestampedLog("Hello") // [1234567890] Hello ``` ## Special Function Syntax ### Infix Notation ```scala object Math { def +(a: Int, b: Int): Int = a.+(b) def -(a: Int, b: Int): Int = a.-(b) } ``` ### Operators as Methods ```scala val list = List(1, 2, 3, 4, 5) list.fold(0)(_ + _) // 15 list.foldLeft(0)(_ + _) // Same (0 /: list)(_ + _) // Same (foldLeft with /: operator) ``` ## Method vs Function ### Method Definition ```scala object Calculator { def add(a: Int, b: Int): Int = a + b } ``` ### Convert Method to Function ```scala val addFunction: (Int, Int) => Int = Calculator.add _ addFunction(3, 5) // 8 ``` ## Summary - Use `def` to define functions - Parameters have explicit types; return types can be inferred - Default parameters and named arguments increase flexibility - Varargs (`_*`) accept variable number of arguments - Recursion is fundamental in functional programming; use tail recursion for efficiency - Anonymous functions provide concise function literals - Higher-order functions take or return functions - Closures capture environment variables - Currying splits multi-parameter functions into single-parameter chains - Methods are defined in classes/objects; functions are values

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →