YouTip LogoYouTip

Scala Closures

In Scala, a closure is a function that can capture and contain free variables from its defining environment. A closure is a function whose return value depends on one or more variables declared outside the function. A closure can access variables outside the function and use them inside the function. Even when the variable's scope has exceeded its defining environment, the closure can still access these variables. The key to a closure is that it can "close over" variables outside the function, making these variables still usable within the function. Consider the following anonymous function: val multiplier = (i:Int) => i * 10 There is a variable i in the function body, which acts as a parameter of the function. Consider the following piece of code: val multiplier = (i:Int) => i * factor There are two variables in multiplier: i and factor. One of them, i, is a formal parameter of the function. When the multiplier function is called, i is assigned a new value. However, factor is not a formal parameter, but a free variable. Consider the following code: var factor = 3 val multiplier = (i:Int) => i * factor Here we introduce a free variable factor, which is defined outside the function. The function variable multiplier defined in this way becomes a "closure" because it refers to a variable defined outside the function. The process of defining this function captures this free variable to form a closed function. Complete Example ## Example object Test { def main(args: Array){ println("muliplier(1) value = " + multiplier(1)) println("muliplier(2) value = " + multiplier(2)) } var factor =3 val multiplier =(i:Int)=> i * factor } [Run Example Β»](#) Executing the above code, the output result is: $ scalac Test.scala $ scala Test muliplier(1) value = 3 muliplier(2) value = 6 In the following example, the closure function captures the external variable externalVar. When the value of externalVar changes, the calculation result within the closure also changes accordingly. ## Example object ClosureExample1 { def main(args: Array): Unit ={ var externalVar =10 val closure =(x: Int)=> x + externalVar println(closure(5))// Output 15 externalVar =20 println(closure(5))// Output 25 } } Executing the above code, the output result is: 1525 ### Closures as Return Values In the following example, the makeAdder function returns a closure. Different closure instances capture different adder values. ## Example object ClosureExample2 { def main(args: Array): Unit ={ def makeAdder(adder: Int): Int => Int ={ (x: Int)=> x + adder } val addFive = makeAdder(5) val addTen = makeAdder(10) println(addFive(3))// Output 8 println(addTen(3))// Output 13 } } Executing the above code, the output result is: 813 * * * ## Types of Variables Captured by Closures Closures can capture different types of variables, including value types and reference types. In the following example, the addMessage closure captures the messages variable and can modify it. ## Example object ClosureExample3 { def main(args: Array): Unit ={ var messages = List("Hello", "World") val addMessage =(msg: String)=> messages = messages :+ msg addMessage("Scala") println(messages)// Output List(Hello, World, Scala) } } Executing the above code, the output result is: List(Hello, World, Scala) * * * ## Closures and Functional Programming Closures are an important concept in functional programming and are widely used in techniques such as higher-order functions and currying. In the following example, the highOrderFunction function takes a function as a parameter. The passed closure captures the external variable externalVar. ## Example object ClosureExample4 { def main(args: Array): Unit ={ def highOrderFunction(f: Int => Int, x: Int): Int = f(x) val externalVar =5 val closure =(x: Int)=> x + externalVar println(highOrderFunction(closure, 10))// Output 15 } } Executing the above code, the output result is: 15
← Scala StringsCurrying Functions β†’