Understanding closures in Scala

Keywords: Programming Scala Lambda

First of all, we need to distinguish the differences between Scala functions and methods, which are two different concepts in scala. Only when we understand these two concepts can we understand the currification.


scala> def add(x:Int, y: Int) = x + y

add: (x: Int, y: Int)Int

scala> add(1, 2)

res0: Int = 3



scala> val add_f = (x: Int, y: Int) => x + y

add_f: (Int, Int) => Int = <function2>

It can be seen from the content add_f Is a function Function

scala> add_f(1, 2)

res1: Int = 3


First of all, you should know that the content to the right of the = sign (X: int, Y: int) = > x + y is a function body

Methods can only be received with def. Functions can be received with def or val.

When a function is received with def, it will no longer be displayed as a function and will be converted to a method

Method can omit parameter, function can't. A function can be used as an argument to a method.



scala> val a = () => 100

a: () => Int = <function0>

scala> val a = => 100

<console>:1: error: illegal start of simple expression


See here: Val a = = > 100 / / error occurs when the function parameter is empty



Understanding closure

scala> def add(x:Int) = (y:Int) => x + y

addBase: (x: Int)Int => Int


(Y: int) = > x + y is a function body, but curly brackets are left and right omitted!


add can be understood as a method whose return value is a function

When a specific parameter is given to a method, a specific function is returned. When the parameter of a method is different, the function returned is also different. for example

Look at the following:

scala> val addOne = add(1)

addOne: Int => Int = <function1>

scala> addOne(3)

res2: Int = 4

Look again:

scala> val addTwo = add(2)

addTwo: Int => Int = <function1>

scala> addTwo(3)

res3: Int = 5


Then we can introduce the concept of closure.

In a block, you can refer to the methods of external local variables, and explain that a block is not only simple code, but also includes the external "environment". A block like this is called a closure. The usual local variable does not exist at the end of the method execution, but if it is included in the closure, the local variable will also exist for the duration of the closure.

That is to say, the function body is affected by the external environment. A closed block of code includes the external environment (the context environment outside the function), that is, the closure.



In the end, we will talk about currification

Currification refers to the process of changing the original method of accepting N parameters into a new function of accepting one parameter.

In fact, the above closure code is the process of currification. Here's the second way of writing.


scala> def add(x:Int)(y:Int) = x + y

add: (x: Int)(y: Int)Int

scala> add(2)(3) //Try calling directly

res5: Int = 5

Try to call the currierization, and continue with the following

scala> val addOne = add(1) _

addOne: Int => Int = <function1>

scala> addOne(3)

res6: Int = 4

Continue below

scala> val addTwo = add(2) _

addTwo: Int => Int = <function1>

scala> addTwo(3)

res7: Int = 5


Expand the currification process above

(personal understanding of corrilization is similar to that of composite function):


scala> def add(x:Int)(y:Int)(z:Int) = {x+y+z}

add: (x: Int)(y: Int)(z: Int)Int


scala> add(10)(20)(30)

res1: Int = 60


//The return value is understood as a function

scala> val addOne = add(100)_

addOne: Int => (Int => Int) = $$Lambda$1131/181022659@36df4c26


//The return value is understood as a function

scala> val addTwo = addOne(200)

addTwo: Int => Int = $$Lambda$1134/1397187309@6c421123


//The return value is no longer a function

scala> val sum = addTwo(300)

sum: Int = 600



Baidu Encyclopedia definition: in computer science, Currying is a technology that transforms a function that accepts multiple parameters into a function that accepts a single parameter (the first parameter of the original function), and returns a new function that accepts the remaining parameters and returns the result. This technique was named after the logician Haskell Curry by Christopher Strache, although it was invented by Moses Schnfinkel and Gottlob Frege.


From a mathematical point of view, this is a process of solving function elimination:


def f(x:Int,y:Int)=x+y

def g(x:Int)=f(x,1)

def z=g(1)


that z It can also be written as follows: def z=(x:Int)=>(y:Int)=>x+y

Posted by sactown on Tue, 05 Nov 2019 08:25:54 -0800