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

Behavior: login, JDBC, read database

Attributes: user name, password

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.

Function advanced

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
    }

    println(dualEval(add, 1, 2))

    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