Introduction and summary of functional programming (with code)
Recently, I have been reading the introductory classics of functional programming. I have summarized it myself. If you are interested or need it, you can take a look.
1. What is functional programming
Functional programming is mainly based on mathematical functions and its ideas, so let’s first review the functions in mathematics
y = f(x)
That is, the function f(x) takes x as the parameter and y as the result. x and y can be any numbers, which contains several key points:
1. The function must always receive a parameter
2. The function must always return a value
3. The function should run according to the received parameter (such as x), not the external environment
4. For a given x, will only output the only y
Let us understand from an example
// 一个计税函数 var percentValue = 5; var calculateTax = (value) => {return value/100 * (100 + percentValue)};
Use functions in mathematics to analyze this function, first look at the third item, the function should be based on the received parameters rather than the external environment. The function calculateTax here relies on the external percentValue. Therefore, this function cannot be called a function in the mathematical sense. So how can we transform it into a function in the mathematical sense? Very simple
var calculateTax = (value,percentValue) => {return value/100 * (100 percentValue)};
Now this function can be called a real function .
Now let’s define functional programming in simple technical terms: Functional programming is a paradigm in which a function completes its own logic relying solely on input and output. This ensures that the function returns the same result when called multiple times. The function does not change any external environment variables.
2. Reference transparency
According to the definition of the function, we can conclude that all functions will return the same value for the same input and output. This property of a function is called referential transparency
As an example
var identity = (i) => { return i };
We define a simple function that does not rely on global variables inside the function, it will simply return the input. Now suppose it is applied between other function calls like
sum(4,5) + identity(1);
According to the definition of referential transparency, we can convert it to
sum(4,5) + 1;
This process is called replacement model, so you The result of the function can be directly replaced (mainly because the function's logic does not depend on other global variables).
Since the function returns the same value for a given input result, we can actually cache it. For example, we have a function "factorial" to calculate factorial. It takes an argument to calculate its factorial, for example the factorial of 5 is 120. When the user enters the factorial of 5 for the second time, due to reference transparency (the same result is returned for the same input), we know that the result is 120, but the machine does not know it. We need to let the machine cache the result so that future calls can directly return the result. Instead of having to calculate it again. This shows the importance of referential transparency and cacheable code in functional programming.
3. Functional, declarative and abstract
Functional programming advocates declarative programming and writing abstract code
What is declarative programming
Suppose we want to print out all the elements in an array, we can use the following method
var array = [1,2,3]; for(let i = 0; i < array.length; i++){ console.log(array[i]) }
In this code, we tell the code exactly how to do it. Such as: getting the length of the array, looping the array, and getting each element by index. This is imperative programming. Imperative programming advocates telling the compiler what to do.
Let’s look at another way
var arr = [1,2,3]; arr.forEach((ele) => { console.log(ele) })
In the above code, we have removed getting the array length, looping the array, using index to get the array elements, etc. We only care about what to do (i.e. printing array elements), getting the array length, looping, etc. are all done by the machine for us. We only need to care about what to do, not how to do it. This is declarative programming
Functional programming Programming advocates creating functions in an abstract manner that can be reused elsewhere in the code.
4. Pure function
What is a pure function? A pure functional function returns the same output for a given input. For example, the double above
var double = (value) => value * 2;
is a pure function because it always returns the same output for the same input. Pure functions follow referential transparency, so we can simply replace double(5) with 10. So what’s the cool thing about pure functions? Let’s take a look
1.4.1 Pure functions produce testable code
Impure functions have side effects. Let’s take the previous tax calculation function as an example to illustrate this function
var percentValue = 5; var calculateTax = (value) => {return value/100 * (100 + percentValue)};
It is not a pure function, mainly because it depends on the external environment to calculate its logic. When the external environment changes, it will affect the result. Therefore, the main characteristic of a pure function is that it does not depend on any external variables and should not change any external variables. If you change external variables, it may cause changes in the behavior of other functions, that is, produce side effects, which can make the behavior of the system unpredictable.
1.4.2 Reasonable code
We should infer the function of the function through its name, such as double function
var double = (value) => value * 2;
我们可以通过函数名轻易的推出这个函数会把给定的数值加倍,因此根据引用透明性,我们可以直接把 double(5) 替换成 10。还有一个例子,Math.max(3,4,5,6) 结果是什么?虽然我们只看到了函数的名字,但是我们很容易看出结果,我们看到实现了吗?并没有,为什么,就是因为 Math.max 是纯函数啊!!!
5、 并发代码
纯函数允许我们并发的执行代码,因为纯函数不会改变它的环境,这意味着我们根本不需要担心同步问题。当然,js 是单线程的,但是如果项目中使用了 webworker 来并发执行任务,该怎么办?或者有一段 Node 环境中的服务端代码需要并发的执行函数,又该怎么办呢?
// 非纯函数代码 let global = 'something' let function1 = (input) => { // 处理 input // 改变 global global = "somethingElse" } let function2 = () => { if(global === "something"){ // 业务逻辑 } }
如果我们需要并发的执行 function1 和 function2,假设 function1 在 function2 之前执行,就会改变 function2 的执行结果,所以并发执行这些代码就会造成不良的影响,现在把这些函数改为纯函数。
let function1 = (input,global) => { // 处理 input // 改变 global global = "somethingElse" } let function2 = (global) => { if(global === "something"){ // 业务逻辑 } }
此处我们把 global 作为两个函数的参数,让它们变成纯函数,这样并发执行的时候就不会有问题了。
6、可缓存
既然纯函数对于给定的输入总能返回相同的输出,那么我们就能缓存函数的输出,例如
var doubleCache = (value) => { const cache = {}; return function(value){ if(!cache[value]){ cache[value] = value * 2 console.log('first time') } return cache[value]; } } var double = doubleCache(); double(2) // first time,4 double(2) // 4 // 或者直接使用立即执行函数 var double = ((value) => { const cache = {}; return function(value){ if(!cache[value]){ cache[value] = value * 2 console.log('first time') } return cache[value]; } })() double(2) // first time,4 double(2) // 4
这个函数中,假设我们第一次输入 5,cache 中并没有,于是执行代码,由于闭包的存在,cache[5] = 10,第二次我们调用的时候,cache[5] 存在,所以直接 return 10,看到了吗?这就是纯函数的魅力!!!别忘记这是因为纯函数的引用透明性。
7、 管道与组合
纯函数应该被设计为一次只做一件事,并且根据函数名就知道它所做的事情。
比如 linux 系统下有很多日常任务的命令,如 cat 用于打印文件内容,grep 用于搜索文件,wc 用于计算行数,这些命令一次只解决一个问题,但是我们可以用管道或组合来完成复杂的任务。假设我们需要在一个文件中找到一个特定的名称并统计它的出现次数,在命令行要输入如下指令
cat jsBook | grep -i “composing” | wc
上面的命令通过组合多个函数解决了我们的问题。组合不是 linux 命令独有的,它们是函数式编程范式的核心。
我们把它们称为函数式组合。来看一个 compose 函数的例子
var add1 = (value) =>{ return value+1 }; var double = (value) => {return value*2 }; var compose = (a,b) => { return (c) => { return a(b(c)); } } var doubleAndAdd1 = compose(add1,double); doubleAndAdd1(5) // 打印 5 * 2 + 1 = 11
compose 函数返回一个函数,将 b 的结果作为 a 的参数,这里就是将 double 的结果作为 add1 的参数,来实现了函数的组合。
8、 纯函数是数学函数
还记得我们之前的缓存函数吗,假设我们多次调用 double 对象,那么 cache 中就会变成这样
{ 1: 2, 2: 4, 3: 6, 4: 8, 5: 10 }
假设我们设置 double 的输入范围限制为 1 - 5,而且我们已经为这个范围建立的 cache 对象,因此只要参照 cache 就能根据指定输入返回指定输出。也就是一一对应的关系。
那么数学函数的定义是什么呢?
在数学中,函数是一种输入集合和可允许的输出集合之间的关系,具有如下属性:每个输入都精确地关联一个输出。函数的输入称为参数,输出称为值。对于一个给定的函数,所有被允许的输入集合称为该函数的定义域,而被允许的输出集合称为值域。
上面的定义和纯函数完全一致,例如在 double 中,你能找到定义域和值域吗?当然可以!通过这个例子,可以很容易看到数学函数的思想被借鉴到函数式范式的世界
9、 我们要做什么?
我们将通过学习,构建出一个 ES6-Functional 的函数式库,通过构建的过程,我们将理解如何使用 JavaScript 函数,以及如何在日常工作中应用函数式编程。
10、小结
这一节我们只是简单的介绍了函数式编程的概念,以及什么是纯函数,其中最重要的就是引用透明性。然后研究了几个短小的例子,通过例子来加深对函数式编程的理解。接下来我们将一步一步深入了解函数式编程。
The above is the detailed content of Introduction and summary of functional programming (with code). For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

In the contemporary programming world, Functional Programming (FP for short) has gradually become a popular programming paradigm. It emphasizes using functions as basic building blocks to build programs, and regards the calculation process as the continuous transfer and conversion between functions. In recent years, Go language (also known as Golang) has gradually been widely used in various fields due to its simplicity, efficiency, concurrency safety and other characteristics. Although the Go language itself is not a purely functional programming language, it provides sufficient functionality.

There are many excellent programming techniques in the C++ language, among which functional programming is a very practical technology. Functional programming emphasizes the reusability and flexibility of functions, which can make the code clearer and maintainable. In this article, we will introduce functional programming techniques in C++. 1. Function object A function object is a callable object, which can be regarded as a function. Function objects in C++ can be class objects or function pointers. Function objects can be used in STL algorithms and can also be used as parameters of other functions. Here is a simple

C++ lambda expressions bring advantages to functional programming, including: Simplicity: Anonymous inline functions improve code readability. Code reuse: Lambda expressions can be passed or stored to facilitate code reuse. Encapsulation: Provides a way to encapsulate a piece of code without creating a separate function. Practical case: filtering odd numbers in the list. Calculate the sum of elements in a list. Lambda expressions achieve the simplicity, reusability, and encapsulation of functional programming.

Lazy evaluation can be implemented in Go by using lazy data structures: creating a wrapper type that encapsulates the actual value and only evaluates it when needed. Optimize the calculation of Fibonacci sequences in functional programs, deferring the calculation of intermediate values until actually needed. This can eliminate unnecessary overhead and improve the performance of functional programs.

With the widespread application of C++ in the computer field and the continuous exploration of programming paradigms, functional programming has also become a topic of great concern. In C++, functional programming has many special concepts and syntax, so related questions are often involved in interviews. This article summarizes and answers common interview questions about functional programming in C++. 1. Advantages and Disadvantages of Functional Programming The interviewer may ask you about your understanding of the advantages and disadvantages of functional programming. Functional programming has the following advantages: High readability. Functional programming only focuses on the output of functions

There are five common mistakes and pitfalls to be aware of when using functional programming in Go: Avoid accidental modification of references and ensure that newly created variables are returned. To resolve concurrency issues, use synchronization mechanisms or avoid capturing external mutable state. Use partial functionalization sparingly to improve code readability and maintainability. Always handle errors in functions to ensure the robustness of your application. Consider the performance impact and optimize your code using inline functions, flattened data structures, and batching of operations.

Lambda expression in python is another syntax form of anonymous function. It is a small anonymous function that can be defined anywhere in the program. A lambda expression consists of a parameter list and an expression, which can be any valid Python expression. The syntax of a Lambda expression is as follows: lambdaargument_list:expression. For example, the following Lambda expression returns the sum of two numbers: lambdax,y:x+y. This Lambda expression can be passed to other functions, such as the map() function: numbers=[ 1,2,3,4,5]result=map(lambda

pythonLambda expressions are a powerful and flexible tool for creating concise, readable, and easy-to-use code. They are great for quickly creating anonymous functions that can be passed as arguments to other functions or stored in variables. The basic syntax of a Lambda expression is as follows: lambdaarguments:expression For example, the following Lambda expression adds two numbers: lambdax,y:x+y This Lambda expression can be passed to another function as an argument as follows: defsum( x,y):returnx+yresult=sum(lambdax,y:x+y,1,2)In this example
