# Scala functional programming

## Functional programming

### Object oriented programming OOP

#### solve the problem

Decompose objects, behaviors and attributes, and then solve problems through object relationships and behavior calls.

Objects: users

Scala is a completely object-oriented programming language

The nature of objects: an encapsulation of data and behavior

### Functional programming

Functional programming is a programming method, which regards computer operation as the calculation of function. The most important foundation of functional programming language is λ lambda calculus, and λ The function of calculus can accept the function as input (parameter) and output (return value). [1]

Compared with instruction programming, functional programming emphasizes that the calculation of functions is more important than the execution of instructions.

Compared with procedural programming, the calculation of functions in functional programming can be called at any time.

#### Function basis

##### Basic usage of function
```def sum(x: Int, y: Int): Int = {
x + y
}
```
##### Differences between functions and methods

A collection of program statements to complete a function, which becomes a function

Functions in a class are called methods

##### Function definition
• No parameter, no return value
• No parameter, return value
• With parameters and no return value
• There are parameters and return values
• Multi parameter, no return value
• Multi parameter with return value
```package chapter05

object Test02_FunctionDefine {
def main(args: Array[String]): Unit = {
// No parameter, no return value
def f1(): Unit = {
println("No parameter, no return value")
}
f1()
println(f1())
println("-----------------------")

// No parameter, return value
def f2(): String = {
println("No parameter, return value")
return "This is f2 return value."
}
// f2()
println(f2())
println("-----------------------")

// With parameters and no return value
def f3(name: String): Unit = {
println("With parameters and no return value" + name)
}
println(f3("zihoo"))
println("-----------------------")

// There are parameters and return values
def f4(name: String): String = {
println("There are parameters and return values" + name)
return "This is f4 return value"
}
println(f4("zihoo"))
println("-----------------------")

// Multi parameter, no return value
def f5(name1: String, name2: String): Unit = {
println("Multi parameter, no return value")
println(name1 + "and" + name2 + "say hello")
}
println(f5("zihoo", "gazikel"))
println("-----------------------")

// Multi parameter with return value
def f6(a: Int, b: Int): Int = {
println("Multi parameter with return value")
return a + b
}
}
}
```
##### Function parameters
• Variable parameters
• If there are multiple parameters in the parameter list, the variable parameters are generally placed last
• Parameter default value. Generally, the parameter with default value is prevented from being behind the parameter list
• A parameter with a name. When a value is transferred with a parameter name, the value can be transferred regardless of the order
```package chapter05

object Test03_FunctionParameter {
def main(args: Array[String]): Unit = {
// Variable parameters
def f1(str: String*): Unit = {
println(str)
}
f1("zihoo")
f1("zihoo", "gazikel")
println("----------------------")

// If there are multiple parameters in the parameter list, the variable parameters are placed last
def f2(number: Int, str: String*): Unit = {
println("number:" + number + ", str:" + str)
}
f2(10)
println("----------------------")

// Parameter default value. Generally, parameters with default values are placed behind the parameter list
def f3(name: String = "school"): Unit = {
println("I am at " + name)
}
f3()
f3("home")
println("----------------------")

// Named parameter
def f4(name: String, age: Int):Unit = {
println(s"\${name}\${age}Years old")
}
f4("zihoo", 21)
f4(age = 21, name = "zihoo")
}
}
```
##### Function simplification principle

Save if you can

```package chapter05

object Test04_Simplify {
def main(args: Array[String]): Unit = {

def f0(name: String): String = {
return name
}

// Return can be omitted. Scala will use the last line of the function body as the return value
def f1(name: String): String = {
name
}

// If the function body has only one line of code, you can omit curly braces
def f2(name: String): String = name
// If the return value type can be inferred, it can be omitted
def f3(name: String) = name

// If there is a return, the return value type cannot be omitted and must be specified
// If the function explicitly declares unit, even if the return keyword is used in the function body, it will not work
def f5(name:String):Unit = {
return "this return It doesn't work"
}
println(f5("zihoo"))

// Scala can omit the equal sign if it expects a type with no return value
def f6(name: String) {
println("The equal sign can be omitted")
}

// If the function has no parameters but declares a parameter list, parentheses can be added or not when calling
def f7() = {
println("f7")
}
f7()
f7

// If the function does not have a parameter list, the parentheses can be omitted and must be omitted when calling
def f8 {
println("f8")
}
f8

// If you don't care about the name and only care about logical processing, you can omit the function name
// Anonymous function, lambda expression
(name: String) => { println(name) }
}
}
```

So how to call an anonymous function without a name?

Next, let's talk about the use of lambda expressions in detail.

##### Higher order function

Functions can be passed as values

```package chapter05

object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
def f(n: Int): Int = {
println("f call")
n + 1
}

val result = f(123)
println(result)

// Functions are passed as values
val f1: Int => Int = f
val f2 = f _
println(f1) // chapter05.Test06_HighOrderFunction\$\$\$Lambda\$5/1908923184@4563e9ab
println(f1(23))
println(f2) // chapter05.Test06_HighOrderFunction\$\$\$Lambda\$6/431687835@11531931
println(f2(35))
}
}

```

Functions can be passed as arguments

```package chapter05

object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
// Functions are passed as arguments
// Define binary calculation function
def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
op(a, b)
}

def add(num1: Int, num2: Int): Int = {
num1 + num2
}

dualEval((a, b) => {
a + b
}, 10, 20)
}
}

```

Functions can be returned as function return values

```package chapter05

object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
// Functions can be returned as function return values
def f5(): Int => Unit = {
def f6(a: Int): Unit = {
println("f6 call" + a)
}
// Return function directly
f6
}

println(f5()) // chapter05.Test06_HighOrderFunction\$\$\$Lambda\$9/1975358023@7d417077
f5()(26)
}
}

```
###### Case practice

Data processing for collections

```package chapter05

object Test07_Practice_Collection {
def main(args: Array[String]): Unit = {

val arr: Array[Int] = Array(12, 45, 75, 98)

// Process the data, abstract the operation, and return a new array after processing
def arrayOperation(arr: Array[Int], op: Int=>Int): Array[Int] = {
for(elem <- arr) yield op(elem)
}

// Define a + 1 operation
def addOne(elem: Int): Int = {
elem + 1
}

// Call function
val newArray: Array[Int] = arrayOperation(arr, addOne)
println(newArray.mkString(","))

// Pass in anonymous function
val newArray2: Array[Int] = arrayOperation(arr, (elem) => elem * 2)
println(newArray2.mkString(","))

}
}
```
##### Anonymous function

Function without name

##### Higher order function case
1. Define an anonymous function and assign it as a value to the variable fun. The function has three parameters: int, string and char, and the return value type is Boolean

It is required to call the function fun (0, '', '0') to get the return value of false, and return true in other cases

2. Define a function func, which receives an Int type parameter and returns a function (recorded as f1). The function f1 returned by it receives a String type parameter and also returns a function (recorded as f2). Line spacing is f2 to receive a Char type parameter and return a Boolean value.

It is required to call func(0)("")('0 ') to get the return value of false, and return true in other cases

```package chapter05

object Test08_Practice {
def main(args: Array[String]): Unit = {
// Exercise 1
val fun = (i: Int, s: String, c: Char) => {
if (i == 0 && s == "" && c =='0') {
false
} else {
true
}
}

println(fun(0, "", '0'))
println(fun(1, "", '0'))

def func(i: Int): String => Char => Boolean = {
def f1(str: String): Char => Boolean = {
def f2(c: Char): Boolean = {
if (i == 0 && str == "" && c =='0') {
false
} else {
true
}
}
f2
}
f1
}
}
}
```
##### Function coritization & closure

Closure: if a function accesses the value of its internal (local) variable, the function and its environment are called closures.

Function coritization: program multiple parameter lists from multiple parameters of a parameter list.

##### recursion

A function (or method) calls itself in the function (method), which is called recursive call.

```package chapter05

object Test10_Recursion {
def main(args: Array[String]): Unit = {
println(fact(5))
}

// Recursive implementation of factorial computation
def fact(n: Int): Int = {
if(n==1)
1
else
(n - 1) * n
}
}
```
##### Control abstraction

Value call: pass the calculated value

```package chapter05

object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {
// Value transfer parameter
def f0(a: Int): Unit = {
println("a:" + a)
}
f0(23)

def f1(): Int = {
println("f1 call")
12
}
f0(f1())
}
}
```

Call Name: pass the code

```package chapter05

object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {

def f1(): Int = {
println("f1 call")
12
}
f0(f1())

println("-------------")
// Named parameter
def f2(a: => Int): Unit = {
println("a:" + a)
println("a:" + a)
}
f2(f1())

f2({
println("This is a code block")
29
})
}
}
```
##### Inert function

When the return value of the function is declared as lazy, the execution of the function is delayed until we take this value for the first time. This function is called inert function.

```package chapter05

object Test13_Lazy {
def main(args: Array[String]): Unit = {
lazy val result: Int = sum(13, 47)

println("1. function call")
println("2. result = " + result)

def sum(a: Int, b: Int): Int = {
println("3. sum call")
a + b
}
}
}
```

Keywords: Big Data

Added by johnsonzhang on Wed, 05 Jan 2022 06:13:34 +0200