What is functional programming

The convention is to ask questions first:

  1. What is functional programming
  2. To solve what problem
  3. How did it work out
  4. Scala’s approach to functional programming

Background story

The background of functional programming is that Moore’s Law is gradually failing today, and multi-core multi-node concurrency is the mainstream development direction in the future. But concurrency is inherently plagued by thread insecurity, poor state maintenance, and lock blocking. Functional programming does not have this problem because it guarantees, in principle, the same result as a function without sharing variables.

Try to answer the question:

  1. Function is a mapping relation of data. Function, as one of the roles in the programming paradigm, can be passed as a variable, and supports high-order function, partial function, Currification and other functions in line with the syntax of function characteristics.
  2. Functional programming is a way to solve problems. Although it is not the only solution, it is an “elegant” programming paradigm for solving problems in scenarios with high concurrency and complex function mappings.
  3. Functional programming has some principles, such as “invariants” and “pure functions”, to ensure thread safety in high concurrency scenarios.

Functional programming is a “programming paradigm”, a methodology for how to write programs.

How a function is defined

[return type] = {// method body: a series of code}

/ / sample
def funcDemo(a:Int,b:String) :Unit= {
    // func body
    // There is no return keyword. The last line is the return value
}
Copy the code

Function keyword: def

Function name: funcDemo

A :Int,b:String

The output parameter type is Unit

Common function types

Higher-order functions

Higher-order abstract functions: Higher-order functions are those that take function objects as arguments.

Functions such as Map() and Filter() are higher-order functions.

val map_test = Array(1.2.3.4.5)
var tmp=map_test.map((i:Int) => i * i)
println("Processed list:" + tmp.mkString(","))
/** processed list: 1,4,9,16,25 */
Copy the code

Anonymous functions

Function body: The argument list is to the left of the arrow and the function body is to the right.

println("Start anonymous function test:")
// Define a calculator with three parameters, two values, and a method that computes the result of two values
def col(i:Int,j:Int,func:(Int.Int) = >Int) :Int= func(i,j)

// Pass an anonymous function
println("Anonymous addition:" + col(1.2,(x:Int,y:Int) => x + y))

/*** results start anonymous function test: anonymous addition: 3 */
Copy the code

Partial function

When a partial application function is created, Scala internally creates a new class with a special apply() method.

A partial function is when you have multiple parameters, you have a shell, and you fix some parameters, right?

In the example, add2 is a partial of the add function

def add(a:Int,b:Int) :Int= a + b
def add3(i:Int) :Int = add(3,i)
def add2(i:Int) :Int = add(2,i)

println("Parameter +2:" + add2(5))
println("Parameter +3:" + add3(5))

/*** result argument + 2:7 argument + 3:8 */
Copy the code

Function characteristics

closure

A closure is a function function whose return value depends on one or more variables declared outside the function.

Closures can generally be thought of simply as another function that accesses local variables within a function.

It refers to a variable defined outside the function, and the process of defining the function is to capture the free variable to form a closed function.

var factor = 3

// Define closure functions. "closure" is a variable whose type is function that returns an anonymous function applied to the argument * factor variable
val closure = (i : Int) => i * factor
Copy the code

Currie,

Corrification solves multi-parameter problems. When the parameters of a function are sufficient and the maintenance cost is high, the current solutions mainly include the following three methods:

  1. Preserve multi-parameter functions (hard rigor)
  2. If the parameter is passed as a List, it is prone to security problems
  3. Currie (Currying)

Currization definition:

The process by which a function that takes two arguments becomes a new function that takes one.

The new function returns a function that takes the original second argument.

Example:

// Normal multi-argument function
def add (a:Int, b:Int) = a + b

// The currified function is passed one argument at a time and returns the new function
def add(a:Int) = (b:Int) => a + b
/** The first step returns an anonymous function, and the second function returns the sum of the two functions */

// Also supports multi-parameter definition of Coriolization functions
def add(a:Int)(b:Int) = a + b

// Call the method
add(3) (4)
Copy the code

Why does a function need to be Currified?

Currization is not necessary in theory, but is necessary in practice. The essence of Corrification is to spell out a multi-parameter function from a single-parameter function, which has the property of being another function that takes only a few parameters. This is so important for functional languages that it simplifies a lot of things.

And it’s the basis of lazy computing.

The inertia calculation

Key words: lazy

Lazy is the keyword used in Scala to implement lazy assignment. A variable modified with lazy is initialized only when it is first used and evaluated only on the first call. That is, the value is evaluated once, assigned once, and never changed thereafter.

Note: Lazy variables must also be immutable variables of val.

val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val past = dateFormat.format(new Date())
lazy val now = dateFormat.format(new Date())
// Sleep for 10 seconds
Thread.sleep(10000)
println("Time before sleep:" + past)
// When the parameter variable is called, the actual fetch value is initiated, the time difference is 10 seconds
println("Time after sleep:" + now)
/** Time before sleep: 2021-09-10 15:38:23 Time after sleep: 2021-09-10 15:38:33 */
Copy the code

Functional programming principles

  1. The function is first class citizen

A function can be assigned to another variable as an argument, passed in to another function, or returned as a value from another function.

Higher order functions.

  1. Just use “expression”, not “statement”

“Expression” is a pure operation that always returns a value; A statement is an operation that does not return a value. Functional programming requires expressions, not statements. In other words, each step is pure operation and has a return value.

They only care about the calculation, not the “action”.

  1. Functions should be pure (pure functions)

Pure function: a function has no side effects in the execution of the program except that it gives the operation results according to the input parameters. We can call this kind of function pure function.

The core purpose of pure functions is to write code without side effects, and many of its features, including invariants, lazy evaluation, and so on, serve this purpose.

Functional programming emphasizes the absence of “side effects,” meaning that functions remain independent, all they do is return a new value, and nothing else, especially not changing the value of an external variable.

  1. You cannot modify a variable passed to a function
  2. Global variables cannot be modified
  3. For the same input parameter, the return value is always the same
  1. Do not modify the state

To have constant values, do not do state maintenance between different threads, reduce the complexity of multithreaded context procedures.

Leaving variables unchanged means that state cannot be stored in variables. The best example of functional programming that uses parameters to preserve state is recursion.

So: Avoid the for loop, use recursion (overflow problem, use tail recursion)

The difference between functions and methods

  • A function is an object (variable), while a method is a component of the object and cannot exist independently.
  • Methods belong to a class or object and are loaded into the JVM’s method section at run time.
  • Function definitions are not neededdefDefinition;
  • You can assign a function object to a variable that is loaded into the JVM’s heap memory at run time;
  • A function is an object that inherits from FunctionN, which has methods apply, Curried, toString, tupled, and none.

digression

When I read this paragraph in this blog, I felt that technology does not have to be updated. Some essential ideas are permanent, and these internal methods are worth our time, such as the core ideas of Information Theory, System Theory and Cybernetics in the information age.

Familiar with the core, understand the boundary, to do T type of technical people, mutual encouragement:

A lot of new concepts have caught on in recent years, but they were invented in the last century, whether it’s machine learning, deep learning, Python, or functional programming. Why is that? That’s because the technological boundaries have changed, or the technological boundaries of this era have changed.

Every age has its technological boundaries. True engineers know where the boundaries lie, but only amateurs can’t. Buffett says he doesn’t invest in things he doesn’t understand precisely because he sets boundaries.

One of the most important reasons for Apple’s success is that it clearly understands the boundaries of its time and can do its best within those boundaries. You see, many of Apple’s products are epoch-making, but in fact, they were not invented by Apple. For example, the smart phone was first invented by DOCOMO, a Japanese company, and the personal tablet computer was first invented by The UK. The IPod and MP3 were also first produced in Korea. Many of the technologies Apple uses were even 30 years old, but why didn’t anyone know about them until they were invented?

It is precisely because Apple understands the technological boundaries of its time and does its best within them.

To put it more simply, when we are learning a new technology, or using it to do a job, we have to see where the boundaries are. More broadly, like Apple, we should be thinking about where the technological boundaries of our era lie so that we don’t get caught up in an endless technological catch-up.

Reference documentation

  1. Scala Documentation

  2. The Functional Programming Bible

  3. Zhang Dabang Learning recursion (QQ.com)

  4. Scala Functional Programming Guide (I) Introduction to Functional Thinking – zzzzMing – Cnblogs.com

  5. Functional Programming For The Rest of Us | defmacro

  6. A preliminary study on functional programming – Ruan Yifeng’s network log