fp函数式编程

This is the other major programming paradigm. If you are interested in Objected oriented programming, I have written about it here…

这是另一个主要的编程范例。 如果您对面向对象的编程感兴趣,那么我已经在这里写过……

*This article is inspired by Andrei Neagoie’s Advanced concepts in Javascript course. I highly recommend it*

*本文的灵感来自Andrei Neagoie在Javascript课程中的高级概念。 我强烈推荐它*

Here is what to expect from this article:

这是对本文的期望:

  1. Currying

    咖喱

  2. Partial application

    部分申请

  3. Pure functions

    纯功能

  4. Referential transparency

    参照透明

  5. Compose

    撰写

  6. Pipe

We know that Functional Programming has existed for over 60 years. Lisp — a popular programming language was first developed in 1958. The idea of functional programming originates from Lambda calculus — a formal system in mathematical logic.

我们知道函数式编程已经存在了60多年。 Lisp是一种流行的编程语言,最早于1958年开发出来。函数式编程的思想起源于Lambda演算 (一种数学逻辑的形式系统)。

Today, the popularity of functional programming has surged because programming languages built on this paradigm such as Haskell, Scala, and Closure work well with distributed computing. In distributed computing, you have multiple machines interacting with data; but also in Parallel computing where machines work on data at the same time.

如今,函数式编程的普及已经激增,因为基于这种范例构建的编程语言(例如HaskellScalaClosure)可以很好地与分布式计算配合使用。 在分布式计算中,您有多台计算机与数据交互; 而且在并行计算中,机器可以同时处理数据。

Javascript libraries like Redux and React have also popularised the idea of functional programming.

像Redux和React这样的Javascript库也已经普及了函数式编程的思想。

那么,FP到底是什么,我们如何将其用作程序员? (So, what is FP anyway and how can we use it as Programmers?)

Just like OOP, Functional programming is all about separation of concerns. We package our code into separate chunks so that everything is well organized. Each part of our code concerns itself with one thing that it’s good at.

就像OOP一样,函数式编程完全是关注点分离。 我们将代码打包成单独的块,以便所有内容井井有条。 我们代码的每一部分都涉及到自己擅长的一件事。

Classes in OOP divide up properties and methods; FP also separates data and functions. For a functional programmer, the world is data that gets interacted with. Data and functions aren’t one piece or one object.

OOP中的类划分属性和方法。 FP还分离数据和功能。 对于功能强大的程序员而言,世界就是与之交互的数据。 数据和功能不是一件或一件事情。

For a Functional programmer, the world is data that gets interacted with; data and functions aren’t one piece or one object.

对于功能性程序员而言,世界就是与之交互的数据。 数据和功能不是一件或一件事情。

Although there is no one definition of what is or what isn't functional, mostly functional programming languages have an emphasis on simplicity where data and functions are concerned.

尽管没有关于什么是功能或什么不是功能的定义,但是大多数功能编程语言都在关注数据和功能的简单性上强调。

Functions just operate on well-defined data structures like arrays and objects rather than belong to them, unlike OOP and objects.

与OOP和对象不同,函数只是在定义良好的数据结构(如数组和对象)上运行,而不是属于它们。

However, the goals of functional programming are the same as Object-oriented programming:

但是,功能编程的目标与面向对象的编程相同:

  1. Make code more clear and understandable.使代码更清晰易懂。
  2. Make code easy to extend so that as our app grows, and as our programs grow, as the developer team grows, our code still remains easier to extend.使代码易于扩展,以便随着我们的应用程序的增长以及程序的增长,以及开发人员团队的增长,我们的代码仍然易于扩展。
  3. Make code easier to maintain by multiple programmers.使代码易于由多个程序员维护。
  4. Make our code memory efficient by having these reusable functions that act on data.通过使这些可重用函数作用于数据,使我们的代码存储高效。
  5. Keep our code DRY. We avoid repeating ourselves. Our code is clean and efficient.保持我们的代码干燥。 我们避免重复自己。 我们的代码干净高效。

纯功能 (Pure functions)

Unlike OOP where we have the four pillars(Encapsulation, Abstraction, Inheritance, Polymorphism), with FP it all comes down to this concept — Pure functions.

与OOP不同,我们有四个Struts( 封装,抽象,继承,多态 ),而FP则归结为这个概念- 纯函数

The idea here is that there is a separation between the data of a program and the behavior of a program.

这里的想法是在程序的数据和程序的行为之间存在分隔。

And all objects created in FP are immutable — once something is created, it cannot be changed. We avoid things like shared state and adhere to this principle of pure functions. As you will find out, in functional programming, there are a lot of things you can’t do.

并且在FP中创建的所有对象都是不可变的-一旦创建了某些内容,就无法更改它。 我们避免使用共享状态之类的东西,并遵循纯函数的这一原则。 您会发现,在函数式编程中,有很多事情是您做不到的。

A function always has to return the same output given the same input no matter how many times we call it; it cannot modify anything outside of its self — no side effects.

无论我们调用多少次,函数始终必须在给定相同输入的情况下返回相同输出。 它无法修改自身之外的任何内容-没有副作用。

A function always has to return the same output given the same input no matter how many times we call it; it cannot modify anything outside of its self — no side effects.

无论我们调用多少次,函数始终必须在给定相同输入的情况下返回相同输出。 它无法修改自身之外的任何内容-没有副作用。

1.无副作用 (1. No side effects)

Let's have an array to demonstrate

让我们有一个数组来演示

ZTM
ZTM

This function has side effects. Here is how we can tell:

此功能有副作用 。 我们可以这样说:

Does the function modify anything outside of its self?

函数是否会修改自身之外的内容?

Here it does. It modifies the array that lives outside of its self in the global object. Hence we don't know what might happen to the array. Anybody can call it and change it.

在这里。 它修改了位于全局对象自身之外的数组。 因此,我们不知道阵列会发生什么。 任何人都可以调用它并进行更改。

If I call a(array) again, my array is again modified.

如果我再次调用a(array) ,我的数组将再次被修改。

Let’s have another function with side effects

让我们有另一个副作用的功能

We are still modifying the array in our global environment
我们仍在全球环境中修改阵列

2.共享状态 (2. Shared state)

With side effects, you are using a shared state that can interact with anything. Here the order of a function call matters which can also cause a lot of bugs.

具有副作用,您正在使用可以与任何事物交互的共享状态。 在这里,函数调用的顺序很重要,这也可能导致很多错误。

So how can we write something that has no side effects? Something that won’t change whatever our array is?

那么,我们怎么写没有副作用的东西呢? 不会改变数组的东西吗?

Well, we can copy the array inside our function

好了,我们可以在函数内部复制数组

The newArray will be the same exact thing as our global array. Note here that we have used the concat() method instead of doing = which would have given us the reference to the array— remember objects are passed by reference.

newArray将与我们的全局数组完全相同。 请注意,这里我们使用了concat()方法,而不是使用= ,这会给我们对数组的引用-记住对象是通过引用传递的。

So instead of having them point in the same direction, this way we have a new copy of the array.

因此,通过这种方式,我们有了数组的新副本,而不是使它们指向同一方向。

Now we can just do newArray.pop() and return newArray. And we can see that the original array hasn't changed.Although we created a new state inside the function, its a local variable. We are not modifying anything outside of our scoped world.

现在我们可以执行newArray.pop()并返回newArray。 我们可以看到原始数组没有改变,尽管我们在函数内部创建了一个新状态,但它是一个局部变量。 我们不会在我们的范围之外修改任何内容。

And because it doesn't affect the outside world, we know what to expect.

而且由于它不影响外界,所以我们知道会发生什么。

map returns a copy of the array
map返回数组的副本

None of my arrays have changed. We have three distinct arrays. And all these functions have no side effects. They don't affect anything that's outside of their world.

我的阵列都没有改变。 我们有三个不同的数组。 所有这些功能都没有副作用。 他们不会影响世界以外的任何事物。

But here is an interesting case:

但这是一个有趣的情况:

This is not a pure function. console.log() uses the browser to log something to the browser. It’s logging something to the outside world hence modifying something outside of itself hence side effects.

这不是一个纯粹的功能。 console.log()使用浏览器将某些内容记录到浏览器中。 它正在将某些东西记录到外界,从而修改了自身之外的东西,从而带来了副作用。

3.输入应始终导致相同的输出 (3. The input should always result in the same output)

Does the function always return the same output given the same input?

给定相同的输入,函数是否总是返回相同的输出?

Here the result is always the same no matter how many times I run the program. This is also known as Referential transparency.

无论我运行该程序多少次,结果都是一样的。 这也称为参照透明性。

Referential transparency
参照透明

Referential transparency says: If I change the contents of a to 7, can that have any effect on the program? The answer is no because no matter what, if my input is the same, I am always going to get the same output.

引用透明说:如果我更改内容,以7,可以在对程序有什么影响? 答案是否定的,因为无论如何,如果我的输入是相同的,我总是会得到相同的输出。

Note that these functions have no side effects. They are not touching any outside part of their world. Parameters here are local variables.

请注意,这些功能没有副作用。 他们没有触及世界的任何外部。 这里的参数是局部变量。

我们可以拥有100%的纯函数吗? (Can we have 100% pure functions?)

No, we can’t. Pure functions in a literal sense can’t do anything. A program can’t exist without side effects.

不,我们不能。 从字面上看,纯函数无法执行任何操作。 没有副作用就不可能存在程序。

Input-output is a side effect. console.log is a side effect — that is all communication with the outside world.

输入输出是一个副作用。 console.log是一个副作用-与外界的所有交流。

Pure functions in a literal sense can’t do anything. A program can’t exist without side effects.

从字面上看,纯函数无法执行任何操作。 没有副作用就不可能存在程序。

We can't run any code without having the side effect of interacting with the browser; we can’t have a website with just pure functions.

如果没有与浏览器交互的副作用,我们将无法运行任何代码。 我们不能拥有仅具有纯功能的网站。

Browsers have to make Fetch calls, HTTP calls to the outside world. We have to interact with the dom and manipulate what's on the website.

浏览器必须进行Fetch调用HTTP调用 到外面的世界。 我们必须与dom互动并操纵网站上的内容。

So we can agree that the goal here is not to make everything pure functions; rather the goal is to minimize side effects.

因此,我们可以同意,这里的目标不是使所有功能都成为纯函数。 相反,目标是最大程度地减少副作用。

The idea is to organize your code with a specific part that has side effects so that when you have a bug, you know right away where to go(database calls, API calls, input-output) because this is normally where side effects are happening. The rest of your code should be just pure functions.

想法是将代码组织成具有副作用的特定部分,这样,当您遇到错误时,您马上就知道要去哪里(数据库调用,API调用,输入输出),因为通常这是发生副作用的地方。 您的其余代码应该只是纯函数。

Purity is more of a confidence level. It cannot be 100%.

纯度更像是一个置信水平。 不能是100%。

Because at the end of the day, we do have to have some sort of global state to describe our application. That's unavoidable.

因为最终,我们确实必须具有某种全局状态来描述我们的应用程序。 那是不可避免的。

The core of functional programming is very simple. We want to build programs that are built with small, reusable, and predictable pure functions.

函数式编程的核心非常简单。 我们希望构建使用小型,可重用和可预测的纯函数构建的程序。

完美的纯功能的特征 (Characteristics of a perfect pure function)

  1. A perfect function should do one task and one task only. We don't want a massive function. We want a simple function that we can test that does one thing well.一个完善的功能应仅执行一项任务和一项任务。 我们不需要庞大的功能。 我们需要一个简单的函数,我们可以对其进行良好的测试。

2. It should have a return statement. Every function should return something. When we give it an input, we expect an output.

2.它应该有一个返回声明。 每个函数都应该返回一些东西。 当我们给它一个输入时,我们期望一个输出。

3. No shared state with other functions.

3.与其他功能没有共享状态。

4. Immutable state. We can modify some of the state within our functions but we always return a new copy of that output. We never modify our global state.

4.不可变状态。 我们可以在函数中修改某些状态,但是我们总是返回该输出的新副本。 我们从不修改我们的全球状态。

5. The function should be predictable. If we understand with certainty what our function does, it makes our code predictable. Functional programming at the end of the day is all about making your code predictable.

5.功能应该是可预测的。 如果我们确定地了解函数的功能,那么它将使我们的代码可预测。 归根结底,函数式编程就是使代码可预测。

Functional programming at the end of the day is all about making your code predictable.

归根结底,函数式编程就是使代码可预测。

函数式编程中的关键概念。 (Key concepts in functional programming.)

幂等 (Idempotence)

One idea that makes this clear is an elevator button. Pressing an elevator call button more than once has no bearing on the final result. Regardless of the number of times you press the button, the elevator is sent to that floor. Idempotent systems, like the elevator, result in the same outcome no matter how many times identical commands are issued.

一个明确的想法是电梯按钮。 多次按下电梯呼叫按钮与最终结果无关。 无论您按下按钮多少次,电梯都会发送到该楼层。 幂等系统(如电梯)无论发出多少次相同的命令,都会产生相同的结果。

Compare this to a function that returns a random number each time.

将此函数与每次返回一个随机数的函数进行比较。

This function always returns a random number between 0 and 1 on every call. It's not predictable.

每次调用时,此函数始终返回0到1之间的随机数。 这是不可预测的。

What idempotence means is given the same inputs, a function always does what we expect it to do.

幂等的含义被赋予相同的输入,一个函数总是按照我们的期望去做。

It’s a lot like pure functions but a little different. If we take the same function

它很像纯函数,但有些不同。 如果我们采用相同的功能

Here no matter how many times I call random, I get 5. The function that console.log’s 5 to the outside world, is idempotent. With multiple calls, it's going to display the same text even though it's not pure.

在这里,无论我叫多少次,都得到5。console.log的5对外界的功能是幂等的。 通过多次调用,即使它不是纯文本,也将显示相同的文本。

Another thing that can be idempotent is deleting a user from a database. When we delete a user from a database, we delete that person once but if I keep calling the function, to delete the same user, it's going to return the same result —an empty field where there are no more users.

可以幂等的另一件事是从数据库中删除用户。 当我们从数据库中删除一个用户时,我们会删除该用户一次,但是如果我继续调用该函数,要删除同一用户,它将返回相同的结果—没有更多用户的空字段。

Idempotence is used a lot in API HTTP requests. You always expect the same result regardless of the number of times a call is made.

幂等在API HTTP请求中使用很多。 无论呼叫多少次,您总是希望得到相同的结果。

Idempotence is valuable in parallel and distributed computation because it makes our code predictable.

幂等在并行和分布式计算中很有价值,因为它使我们的代码可预测。

Another idea is the ability to call yourself over and over inside of yourself and you still get the same result.

另一个想法是能够一遍又一遍地称呼自己,而您仍然得到相同的结果。

Math.abs gives me a positive number or absolute number every time.

Math.abs每次给我一个正数或绝对数。

But no matter what, calling this function over and over inside of itself always returns with the same thing. And so this is a guarantee of code being predictable.

但是无论如何,一遍又一遍地调用此函数总是返回相同的结果。 因此,这是代码可预测的保证。

命令式与声明式 (Imperative vs declarative)

Imperative code is code that tells the machine what to do and how to do it.

命令性代码是告诉机器做什么和如何做的代码。

Declarative code tells it what to do and what should happen. It doesn't tell the computer how to do things.

声明性代码告诉它做什么和应该发生什么。 它不会告诉计算机如何做事。

Think about an image tag. It’s declarative. You include it in your code and you expect an image although you don't tell the machine how to display it.

考虑一下图像标签。 它是声明性的。 您将其包含在代码中,尽管您不告诉机器如何显示它,但是您期望得到一个图像。

A computer is better at being imperative. It needs to know how to do things. Human beings on the other hand are declarative.

一台计算机更是当务之急。 它需要知道如何做事。 另一方面,人类是声明性的。

When we looked at the Javascript engine, we saw how machine code is imperative.

当我们查看Javascript引擎时 ,我们看到了机器代码的必要性。

Imperative vs declarative
命令式与声明式

Our machine code tells the computer, for example, to put the variable in that memory space and then take it out here and then modify it there. It’s very descriptive of how to do things vs as we go higher and higher up the chain to a higher-level language, we see declarative behavior.

例如,我们的机器代码告诉计算机,将变量放入该内存空间,然后在此处取出并在此处进行修改。 与如何做事相比,这是非常有描述性的,而随着我们越来越深入到更高层次的语言,我们看到了声明式行为。

We don't have to say hey, this is where you should store the memory. We just declare a variable with some sort of data and we say what needs to get done but not how to do it. The computer takes care of that for us.

我们不必说嘿,这是您应该存储内存的地方。 我们只声明一个带有某种数据的变量,然后说什么需要完成,而不是如何完成。 电脑会为我们处理这些事情。

Another example is for loops.

另一个示例是for循环。

Example 1
例子1
Example 2
例子2

Which one would you say is declarative vs imperative?

您会说哪一个是声明式还是命令式?

Example 1 is imperative. We say declare a variable zero. And then loop for 1000 times. Also, increment i by one every time and finally console.log(i).There is a lot of instructions here.

例1势在必行。 我们说将变量声明为零。 然后循环1000次。 另外,每次将i递增1,最后是console.log(i)。 这里有很多说明。

How can we make this more declarative? Example 2 is declarative.Here we don't tell the program what to do or how to do it. I don't tell it to increment i by 1, or loop through things.

我们如何使它更具声明性? 示例2是声明性的,这里我们不告诉程序做什么或如何做。 我不告诉它使i递增1或循环遍历。

Another example of this is jquery. Jquery is more imperative than what we have now like React, Angular, or Vue.

另一个例子是jqueryjQuery比我们现在喜欢的ReactAngularVue更重要

Functional programming helps us be more declarative. We compose functions and we tell our programs what to do instead of how to do it.

函数式编程有助于我们更具声明性。 我们编写函数,并告诉程序做什么而不是怎么做。

But it’s important to note that at the end of the day, our declarative code is either going to end up either compiling down or being processed by something imperative like machine code. We can’t just avoid side effects and data manipulations.

但重要的是要注意,到最后,我们的声明性代码要么结束编译要么被诸如机器代码之类的命令性代码处理。 我们不能仅仅避免副作用和数据操纵。

But it’s important to note that at the end of the day, our declarative code is either going to end up either compiling down or processed by something imperative like machine code. We can’t just avoid side effects and data manipulations.

但重要的是要注意,到最后,我们的声明性代码要么最终要编译,要么由诸如机器代码之类的命令性代码处理。 我们不能仅仅避免副作用和数据操纵。

At the end of the day, something has to manipulate the dom on the webpage or talk to a database.

归根结底,有些东西必须操纵网页上的dom或与数据库对话。

In the case of something like React, it abstracts away a lot of complexity so that we as programmers don't have to do it.

在类似React的情况下,它抽象了很多复杂性,因此我们作为程序员不必这样做。

But the React library or Lisp itself eventually has to compile and do imperative things. The idea here is for us to get a level higher into declarative code so that we can be more productive.

但是React库或Lisp本身最终必须编译并执行命令性的事情。 这里的想法是让我们对声明性代码有更高的了解,从而提高工作效率。

不变性 (Immutability)

This means not changing the state. In OOP we saw classes that you could change. In functional programming, it’s all about immutability.

这意味着不更改状态。 在OOP中,我们看到了可以更改的类。 在函数式编程中,所有内容都与不变性有关。

You are not changing the state but instead, you are making copies of the state and returning a new state every time.

您不是在更改状态,而是每次都在复制状态并返回新状态。

State Mutation
状态突变

We are cloning the obj and so our clone is a pure function. Because no matter how many times I call this function, it's going to clone — it's a pure function.

我们正在克隆obj ,因此我们的克隆是一个纯函数。 因为无论我调用此函数多少次,它都将被克隆-这是一个纯函数。

But you can see that afterward I do obj.name and update the name to Allan. As soon as I do that, the name gets changed to Allan. Here we are mutating the state. We are mutating data in our program.

但是您可以看到,之后我执行obj.name并将名称更新为Allan。 我这样做后, 名称立即更改为Allan。 在这里,我们正在改变状态。 我们正在对程序中的数据进行变异。

In functional programming, the idea of immutability is very important. We can change things inside of our function but we don't want to affect the outside world in our programs.

在函数式编程中,不变性的概念非常重要。 我们可以在函数内部更改事物,但我们不想在程序中影响外部世界。

Ideally, if we want to change the name, we would create a function to do just that.

理想情况下,如果要更改名称,则可以创建一个函数来完成此操作。

source ZTM
源ZTM

结构共享 (Structural sharing)

Here our initial obj James is still there. We have maintained immutability. We are returning copies every time a change is made.

在这里,我们最初的obj James仍然存在。 我们一直保持不变。 每次进行更改时,我们都将退还副本。

Now you might say that this is not very efficient. Because we are just copying things over every time we want to make a change and we run a risk of filling up our memory.

现在您可能会说这不是很有效。 因为我们只是在每次进行更改时都在复制内容,所以我们冒充满内存的风险。

There is something called structural sharing. Functional programming and a lot of places implement this data structure.

有一种叫做结构共享的东西。 功能编程和很多地方都实现了这种数据结构。

Wikipedia
维基百科

The idea behind it is that when a new object or any sort of data structure is created, we don't actually copy everything. If it's a massive object or array, that is very expensive.

其背后的想法是,当创建新对象或任何类型的数据结构时,我们实际上并没有复制所有内容。 如果它是一个庞大的对象或数组,那将是非常昂贵的。

Instead of sharing the whole copy, underneath the hood, what happens is that only the changes that were made to the state would be copied.

而不是在后台共享整个副本,而发生的是仅复制对状态所做的更改。

But the things that don't change, in memory, are actually still there. And this is called structural sharing. With this in mind and the fact that today's memory is fairly cheap, it doesn't make functional programming especially the idea of immutability expensive or wasteful.

但是,内存中不变的事物实际上仍然存在。 这就是所谓的结构共享。 考虑到这一点以及当今的内存相当便宜的事实,它不会使函数式编程特别是不变性的想法变得昂贵或浪费。

We are just saying that hey this data is not mine. So I am just going to copy it and leave the original intact so that other people can use it as well; just like a kid in school who plays with toys but doesn't destroy them so that other kids can play with them too.

我们只是说嘿数据不是我的。 因此,我将复制它并保留原样,以便其他人也可以使用它。 就像在学校里玩玩具但不会破坏玩具的孩子一样,以便其他孩子也可以玩。

We are just saying that hey this data is not mine. So I am just going to copy it and leave the original intact so that other people can use it as well; just like a kid in school who plays with toys but doesn’t destroy them so that other kids can play with them too.

我们只是说嘿数据不是我的。 因此,我将复制它并保留原样,以便其他人也可以使用它。 就像在学校里玩玩具但不会破坏玩具的孩子一样,以便其他孩子也可以玩。

HOF和关闭 (HOF and closures)

HOF is a function that does one or two things:1. Takes one or two functions as arguments

HOF是执行一两个功能的功能:1。 接受一两个函数作为参数

2. Returns another function as a result often called a callback.

2.作为结果返回另一个函数,通常称为回调。

For example,

例如,

A function that returns a function is a HOF
返回函数的函数是HOF

or

要么

It could be a function that takes a function parameter

它可能是一个带有函数参数的函数

Now, this also means we can do Closures.

现在,这也意味着我们可以关闭。

Like objects in Javascript, closures are a mechanism to contain state.

像Javascript中的对象一样,闭包是一种包含状态的机制。

In Javascript, we create a closure whenever a function accesses a variable that is outside of its immediate scope. We simply define a function inside another function and expose the inner function either by passing it or passing it to another function as a variable.

在Javascript中,只要函数访问其直接作用域之外的变量,我们就创建一个闭包。 我们只需在另一个函数内部定义一个函数,然后通过传递内部函数或将其作为变量传递给另一个函数来公开内部函数。

Now I can give this to a variable

现在我可以给一个变量

Now even though the initial closure function was called and we are done with that, because of closure, this increment function remembers the variable declared in the outer scope.

现在,即使调用了初始的关闭函数,并且我们已经完成了该操作,由于关闭,此增量函数会记住在外部作用域中声明的变量。

The variable used by the inner function will be available to it even after the outer function has finished running.Here we are modifying state outside of our function. This increment function is touching state or data that belongs to another function — the closure function.

内部函数使用的变量即使在外部函数完成运行后也可以使用。在这里,我们正在函数外部修改状态。 此递增功能正在触摸状态或属于另一个功能(关闭功能)的数据。

This however doesn’t mean that we can't use closures. They are very powerful. We just have to be careful. Closures only make a function impure if we modified the closed over variable.

但是,这并不意味着我们不能使用闭包。 他们非常强大。 我们只需要小心。 如果我们修改了close over变量,闭包只会使函数不纯。

For example,

例如,

We are using closures here. Also, note that we are not modifying the state like we had before but we still have access to data outside of ourselves. As long as we don't modify and mutate that data, we are still following the functional programming paradigm.

我们在这里使用闭包。 另外,请注意,我们没有像以前那样修改状态,但是我们仍然可以访问自己外部的数据。 只要我们不修改和变异数据,我们仍将遵循函数式编程范例。

Something important here is that we just created private variables. We are able to use closures to create data privacy which is very useful.

这里重要的是我们刚刚创建了私有变量。 我们能够使用闭包来创建数据隐私,这非常有用。

As a user, I can't modify count=55. Maybe it is an important variable that we shouldn’t touch. But because of closures, we still have access to that variable, and we are also making sure others don't modify it.

作为用户,我无法修改count = 55 。 也许这是我们不应该碰到的重要变量。 但是由于闭包,我们仍然可以访问该变量,并且还要确保其他人不要对其进行修改。

Closures get used a lot in functional programming for this specific reason; we just have to be careful not to modify the state.

由于这个特定的原因,闭包在函数式编程中被大量使用。 我们只需要注意不要修改状态。

咖喱 (Currying)

This is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions each with a single argument.

这是一种将需要多个参数的函数的求值转换为对每个函数具有一个参数的函数序列求值的技术。

You take a function that can take multiple parameters and instead, using currying, modify it into a function that takes one parameter at a time.

您采用了一个可以采用多个参数的函数,而是使用currying将其修改为一次仅采用一个参数的函数。

Let's look at an example

让我们看一个例子

We can use currying here so that our function which takes multiple parameters at a time can take a parameter at a time.

我们可以在此处使用currying,以便我们的函数一次获取多个参数可以一次获取一个参数。

Now because of closures, we have access inside of the b function to the a variable.

现在由于闭包,我们可以在b函数内部访问a变量。

I am giving the function one parameter at a time.
我一次给函数一个参数。

Why is this useful?Because now I can create multiple utility functions out of this. For example:

为什么这有用? 因为现在我可以用它创建多个实用程序函数。 例如:

Now, I have called this function once and for the rest of its time is going to remember this piece of data forever until we finish running the program.

现在,我已经调用了此函数一次,在剩下的时间里,它将永远记住该数据,直到我们完成运行程序为止。

So that 10 years from now if we finally remember we have this curriedMultiplyBy5, I can use it to multiply anything we want by 5. Let's say 4.

因此,从现在开始的10年后,如果我们最终记得我们拥有了curriedMultiplyBy5,我可以使用它将我们想要的任何值乘以5。假设4。

Instead of running this function over and over, I have run it once and now this curriedMultiplyBy5 is there for us to use.So if its a function that gets called many times, we only run this part of the function: (b) => a*b

我没有一次又一次地运行此函数,而是运行了curriedMultiplyBy5这个函数供我们使用,因此,如果该函数被多次调用,我们只运行该部分函数: (b)=> a * b

And currying reminds you of those methods on prototypes shared amongst objects; they are trying to save on memory or at least reduce on the work that our computers have to do.

而curring使您想起对象之间共享的原型上的那些方法; 他们试图节省内存或至少减少我们计算机必须完成的工作。

部分申请 (Partial Application)

This gets confused with currying. It’s only slightly similar.

这与欺骗混为一谈。 它只是有点相似。

This is a way for us to partially apply a function. It’s a process of applying a function with a smaller number of parameters.

这是我们部分应用功能的一种方式。 这是应用带有较少数量参数的函数的过程。

It means taking a function, applying some of its arguments into the function so it remembers those parameters. It uses closures to later on be called with the rest of the arguments.

这意味着采用一个函数,将其一些参数应用到函数中,以便记忆这些参数。 它使用闭包稍后再与其余参数一起调用。

We can say that this code uses partial application; but what if we had 3 parameters?
我们可以说这段代码使用了部分应用程序; 但是如果我们有3个参数怎么办?

Partial application says I want to apply a portion of the parameters, for example, and then the next time I call that function, I wanna apply the rest of the arguments.

例如,部分应用程序说我想应用一部分参数,然后在下次调用该函数时,我想应用其余的参数。

But let's see the curried version first. Here we would just add another parameter

但是,让我们先看看咖喱版本。 在这里,我们只需添加另一个参数

Partial application says no I want you to call the function once and then apply the rest of the arguments to it. That means on the second call I expect all the arguments.

部分应用程序说不,我希望您一次调用该函数,然后将其余参数应用到该函数。 这意味着在第二次通话中,我期望所有参数。

So now if I do partialMultiplyBy5(), we have 5 bound to the first parameter using bind().

因此,现在如果我执行partialMultiplyBy5(),我们将使用bind()将 5绑定到第一个参数

Now if I do:

现在,如果我这样做:

I have partially applied a parameter — the a parameter and then I get to call the rest of the parameters b and c. That's the main difference between currying and partial application.

我已经部分应用了一个参数-a参数 然后我调用其余的参数bc 。 这是currying和部分应用程序之间的主要区别。

Partial application says on the second call I expect all the arguments. Currying says I expect one argument at a time.

部分应用程序在第二次调用时说我希望所有参数。 库里说,我希望一次能有一个论点。

快取 (Caching)

This is a way of storing values so you can use them later on. Ideally, you can think of caching as a backpack that you can take to school.

这是一种存储值的方法,因此您以后可以使用它们。 理想情况下,您可以将缓存视为可以带到学校的背包。

Instead of going all the way home when you need something, like a pencil, you have a small box on your back that holds items that you need.

当您需要诸如铅笔之类的东西时,您不必一路回家,而是在背面有一个小盒子,里面放着您需要的物品。

Caching is a way for us to speed up programs and hold some piece of data in an easily accessible box.

缓存是我们加快程序速度并将某些数据保存在易于访问的框中的一种方式。

记忆化 (Memoization)

Is a specific form of caching. It's used a lot in Dynamic programming.

是缓存的一种特定形式。 它在动态编程中使用很多。

Let's say we have a function that says we want to addto80

比方说,我们有,说我们要addto80功能

Now if I run this function again, I will have to go through the same steps to add n to 80.

现在,如果我再次运行此函数,则必须执行相同的步骤将n加到80。

We have done the calculation 3 times. But what if this function takes a really long time?

我们已经完成了3次计算。 但是,如果此功能需要很长时间,该怎么办?

Every time we run this function, we will have to run long time 3 times. We go through the steps one by one even though we’ve done the same calculations.

每次运行此功能时,我们都必须长时间运行3次。 即使我们进行了相同的计算,我们也会一步一步地进行操作。

Is there a way that we can optimize this?This is where we can use caching and memoization.

有什么方法可以优化它吗?这是我们可以使用缓存和备忘录的地方。

Let's improve the above function by doing something different.

让我们通过做一些不同的事情来改进上述功能。

Simple property access is O(1) with a hash table.
简单属性访问是带有哈希表的O(1)。

The first time I run this function, I get long time. The first pass through went through the else part and did this calculation that hypothetically is going to take a long time.

第一次运行此功能时,我会花很长时间 。 第一遍经过其他部分,并进行了此计算,假设这将花费很长时间

This is a simple example but this could also be a calculation that takes a really long time.

这是一个简单的示例,但这也可能是花费很长时间的计算。

If I run this function, the first time around, we call long time and we calculate to 85 but the second time around because this value was in the cache, we didn't have to do this long calculation and we just returned it immediately.

如果我第一次运行此函数,则调用长时间,然后我们将其计算为85,但是第二次运行,因为此值在高速缓存中 ,我们不必进行长时间的计算,而是立即将其返回。

那么到底是什么记忆呢? (So what is memorization exactly?)

It is a specific form of caching that involves caching the return value of a function that is based on its parameters. If the parameter of the function doesn't change, then it is memoized.

这是一种特殊的缓存形式,涉及缓存基于函数参数的返回值。 如果函数的参数未更改,则会被记忆。

It uses the cache because it has calculated the same thing before with the same parameters and will return the same version of the function. If the parameter changes, then it's going to calculate both times.

它使用缓存是因为它之前使用相同的参数计算了相同的事物,并且将返回该函数的相同版本。 如果参数更改,则将计算两次。

Memoization is simply a way to remember a solution to a subproblem so you don't have to calculate it again.

记忆只是记住一个子问题解决方案的一种方法,因此您无需再次计算。

Let’s improve our memorized function

让我们改善记忆功能

Ideally, we don't want to fill the cache in the global scope. It’s good practice if the cache lives inside the function and it's not polluting the global scope.

理想情况下,我们不想在全局范围内填充缓存。 如果缓存位于函数内部并且不污染全局范围,则是一个好习惯。

The problem now is that we reset the cache every time the function gets called. So the cache becomes an empty object.

现在的问题是,每次调用该函数时,我们都会重置缓存。 因此,缓存成为空对象。

To get around this we can use closures in Javascript.

为了解决这个问题,我们可以在Javascript中使用闭包

Our function remembers that the parameter has not changed. It’s going to check the cache and say I do not need to do that calculation I already have it.
我们的函数记住该参数未更改。 它要检查缓存,并说我不需要进行计算,因为我已经有了它。

Because of closures, we are able to access the cache inside of the outer function. This allows us to be very efficient with our code. In this sense, we use memorization to optimize our code.

由于闭包,我们能够访问外部函数内部的缓存 。 这使我们的代码效率很高。 从这个意义上讲,我们使用记忆来优化代码。

组成和管道 (Compose and pipe)

This is the most powerful concept in FP.

这是FP中最强大的概念。

Compose means that any sort of data transformation that we do should be obvious. It's kind of like a conveyor belt in a factory.

撰写意味着我们进行的任何类型的数据转换都应该是显而易见的。 有点像工厂的传送带。

First, we have data that gets processed by a function that outputs some sort of data. This then gets processed by another function that outputs that data in a new form and so on and so forth.

首先,我们的数据由输出某种数据的函数处理。 然后由另一个函数处理,该函数以新形式输出该数据,依此类推。

Composability is a system design principle that deals with this relation of components. A highly comparable system provides components that can be selected and assembled in various combinations. This makes it easy to move pieces around to get the desired output based on user-specific requirements.

可组合性是处理组件之间这种关系的系统设计原则。 高度可比的系统提供了可以以各种组合选择和组装的组件。 这使得根据用户特定的需求轻松移动零件以获得所需的输出。

Let's say I want to do something using functional programming but I also want to do two things at a time.Let's say we have a number -50 that gets multiplied by 3. We also want to take the absolute number or remove any negative signs from it. This means that we want to do two things — two functions.

假设我想使用函数式编程来做某事,但我也想一次做两件事。假设我们有一个-50乘以3的数字 。 我们还想获取绝对数字或从中删除任何负号。 这意味着我们想做两件事-两个功能。

How can we compose them together like an assembly line at a factory?

我们如何像工厂的装配线一样将它们组合在一起?

Of course, there are a lot of libraries that let you compose like Ramda. In Javascript, you can use compose(); not to say that it exists in Javascript, its just very common.

当然,有很多库可以让您像Ramda一样编写 。 在Javascript中,您可以使用compose() ; 并不是说它存在于Javascript中,这只是非常普遍。

Let's build one on our own that allows us to multiplyBy3 and also take absolute. In order to do that, I need to compose these two pieces of functionality.

让我们自己构建一个,使我们能够乘法并也取绝对值。 为了做到这一点,我需要组合这两个功能。

Let’s define our own compose function.

让我们定义我们自己的compose函数。

Our function will take the two functions(f, g) — multiplyBy3 & makePositive that act on the data we have
我们的函数将采用两个函数(f,g)—乘法By3和makePositive,它们作用于我们拥有的数据

Now let's define the two functions

现在让我们定义两个函数

Now if I run this I get 150 because 50*3 is 150 and we make that an absolute number by removing the negative.

现在,如果我执行此操作,我将得到150,因为50 * 3为150,我们通过消除负数来使它成为绝对数。

Using compose, we’ve created our own assembly line where we can compose different functions together.

使用compose ,我们创建了自己的组装线,可以在其中组装不同的功能。

Remember the definition, Composability is a system design principle that deals with the relationship between components that can be selected and assembled in various combinations.

请记住定义,可组合性是一种系统设计原则,处理可以选择和组合成各种组合的组件之间的关系。

There is a lot of power here because now we can compose functions and build them together to add extra functionality. We take a piece of data, we take it through all these functions and then we finally have some sort of data that gets outputted.

这里有很多功能,因为现在我们可以组合功能并将它们构建在一起以添加额外的功能。 我们获取一条数据,通过所有这些功能进行处理,然后最终获得某种输出的数据。

All those functions are pure and all those functions are composable.

所有这些功能都是纯函数,并且所有这些函数都是可组合的。

Compose is one of the most common functions you are going to see in a programming language. If you are using functional programming, you are definitely using compose.

Compose是您将在编程语言中看到的最常见的功能之一。 如果使用函数式编程,则肯定使用了compose。

管 (Pipe)

Pipe is the same thing as compose except instead of going from right to left, it goes left to right.

管道与撰写相同,只是管道从左到右而不是从右到左。

We just swap these around so that now with pipe the operations are different. f gets run first over the data. The first parameter that we’ve given compose (multiplyBy3) gets run first, and then g gets run over that data. Make positive gets run last.

我们只是交换它们,以使现在与管道不同的操作。 f首先运行数据。 我们给了compose的第一个参数(multiplyBy3)首先运行,然后g对该数据运行。 让积极向上跑到最后。

For example,fn1(fn2(fn3(50)))

例如, fn1(fn2(fn3 (50) ))

With compose, this is what we can do

使用compose,这就是我们可以做的

(fn1, fn2, fn3)(50)

(fn1,fn2,fn3)(50)

We are saying I want you to evaluate this right to left.Take the data then apply function 3 to it. Whatever comes out of that, apply function 2 to it; whatever comes out of that, apply function 1 to it.

我们要说的是我希望您从右到左进行评估,取数据然后将函数3应用于它。 无论结果如何,都对其应用功能2 ; 无论结果如何,都应对其应用功能1。

Pipe is just the opposite

管道正好相反

pipe(fn3,fn2,fn1)(50)

管道(fn3,fn2,fn1)(50)

These two functions are going to have the same exact output because the functions are the same. They are used interchangeably. You can use whichever you prefer for your readability.

这两个函数将具有相同的确切输出,因为函数是相同的。 它们可以互换使用。 您可以使用任何您喜欢的可读性。

And that's the power of compose. We get tiny functions that are easy to test and we put them together to have powerful results.

这就是撰写的力量。 我们获得了易于测试的微小功能,并将它们放在一起可获得强大的结果。

阿里特 (Arity)

This simply means the number of arguments a function takes.If we look at the compose function, it has an arity of 2; MultiplyBy3 has an arity of 1.

这只是简单地表示一个函数接受的参数数量。如果看一下compose函数,它的偶数为2;否则为0。 MultiplyBy3的偶数为1。

Although it isn't a solid rule, in functional programming, it’s usually good practice to have a fewer number of parameters. The fewer the parameters, the easier it is to use a function.

尽管这不是一个固定的规则,但在函数式编程中,通常最好的做法是减少参数数量。 参数越少,使用功能就越容易。

You can do more flexible things and it makes functions more flexible.

您可以做更多灵活的事情,这会使功能更加灵活。

We can use things like currying or something like compose and pipe and —compose these functions together.

我们可以使用诸如currying之类的东西或诸如composepipe之类的东西,以及将这些函数组合在一起。

The more parameters a function has, the harder it is to compose it with other functions. It doesn't mean its impossible, but it does become more difficult.

函数具有的参数越多,将其与其他函数组合就越困难。 这并不意味着它不可能,但是确实变得更加困难。

So when it comes to Arity, there is no hard right or wrong. But you may want to stick to one or two parameters.

因此,对于Arity而言 ,没有硬性对与错。 但是您可能想要坚持一个或两个参数。

为什么函数式编程如此出色? (Why functional programming is so great?)

The separation of data and functions — or data and the effects that happen on that data.

数据和功能(或数据及其对数据的影响)的分离。

Doing effects and logic at the same time, as in OOP may create side effects that cause a lot of bugs. If multiple things in your program handle some piece of data at the same time, that gets really complicated and it can cause many problems.

如在OOP中那样,同时执行效果和逻辑可能会产生副作用,从而导致许多错误。 如果程序中的多个事物同时处理某段数据,那将变得非常复杂,并且可能导致许多问题。

So the idea of keeping functions small and pure and comparable; doing one thing at a time and doing it well; immutability; the idea that a function takes inputs and returns outputs so that it can be used with other functions allows us to have a predictable program minimizing bugs because everything is so simple.

因此,保持功能小巧,纯净和可比的想法; 一次做一件事情并做好。 不变性 一个函数接受输入并返回输出以便可以与其他函数一起使用的想法使我们可以拥有一个可预测的程序,从而使错误最小化,因为一切都非常简单。

And as long as we are able to combine these little small functions together, we are able to create really complex programs.

只要我们能够将这些小的功能组合在一起,我们就可以创建真正复杂的程序。

It doesn’t mean that functional programming is the answer to everything. But because of its nature, it works well with distributed systems — systems that have different machines all over the world working with each other; or parallelism where multiple things have to happen in parallel

这并不意味着函数式编程可以解决所有问题。 但是由于它的本质,它可以与分布式系统很好地协同工作。 或并行性,其中多个事物必须并行发生

It doesn’t mean that functional programming is the answer to everything. But because of its nature, it works well with distributed systems — systems that have different machines all over the world working with each other; or parallelism where multiple things have to happen in parallel. These functions are pure so there are no strange bugs.

这并不意味着函数式编程可以解决所有问题。 但是由于它的本质,它可以与分布式系统很好地协同工作。 或并行性,其中多个事物必须并行发生。 这些函数是纯函数,因此没有奇怪的错误。

But it also depends on the problem you have. There are times when Object-oriented programming might be better. You are building a fairly tale game and you have clear object characters in the game that have some sort of state and can interact with that state and others can interact with them as well.

但这也取决于您遇到的问题。 有时候面向对象的编程可能会更好。 您正在构建一个相当古老的游戏,并且游戏中具有清晰的对象角色,这些角色具有某种状态并且可以与该状态进行交互,而其他人也可以与它们进行交互。

Or you have an amazon shopping cart where there is clear data that needs to get processed.

或者,您有一个亚马逊购物车,其中有需要处理的清晰数据。

In fact, let’s build an Amazon shopping cart to apply these principles of functional programming that we’ve learned so far.

实际上,让我们构建一个亚马逊购物车,以应用到目前为止所学的这些函数式编程原理。

Functionality

功能性

  1. Add Item to cart加入购物车
  2. Add 3% tax to an item in cart为购物车中的物品加3%税
  3. Buy item买东西
  4. Empty cart空购物车

These are the functions we are going to need

这些是我们需要的功能

These are the functions that are going to affect the Data that we have — the user
这些功能将影响我们拥有的数据-用户
The user
用户

Based on what we've learned, we want to keep these functions pure. We are also applying a bunch of steps to the same data.

根据所学知识,我们希望保持这些功能纯净。 我们还对同一数据应用了一系列步骤。

We can use something like compose to compose all these steps so that function purchaseItem() does all these things here.

我们可以使用诸如compose之类的方法来组合所有这些步骤,以便在这里, purchaseItem()函数可以完成所有这些操作。

But first, how would we approach this without compose?Let's say we receive the user and item as parameters; we will return the user with the new item.

但是首先,我们如何在不编写代码的情况下进行处理?假设我们接收到用户作为参数; 我们将向用户返回新商品。

We know that we want to keep things immutable. We don't want to modify the user, so we will return a new object.

我们知道我们希望保持不变。 我们不想修改用户,因此我们将返回一个新对象。

The third parameter is our purchased item.
第三个参数是我们购买的物品。

Here Kim our user has purchased a laptop with a price of 344 and it's in their purchase history. But that's not all because remember, we have to add a tax and all the other functions we saw. Maybe Kim wants to remove something from the cart. We are being too simplistic here.

在这里,我们的用户 Kim以344的价格购买了笔记本电脑,这是他们的购买历史记录。 但这还不是全部,因为请记住,我们必须添加税金和所看到的所有其他功能。 也许Kim想要从购物车中取出东西。 我们在这里太简单了。

So we need to compose these functions together.

因此,我们需要将这些功能组合在一起。

I have a factory called purchaseItem that takes the data — user and item and we are giving this data to all these functions above. So let's compose all these functions together.

我有一个名为purchaseItem的工厂,该工厂接收数据( 用户项目) ,我们将数据提供给上述所有这些功能。 因此,让我们将所有这些功能组合在一起。

Note that here we have more than two functions. This is part of the reason you should use a library like Ramda or Lodash to use compose because you don't need to implement this yourself. For now, let's do it for the purpose of learning.

请注意,这里我们有两个以上的功能。 这是您应使用Ramda或Lodash之类的库来使用compose的部分原因,因为您无需自己实现此目的。 现在,让我们以学习为目的。

We are using the spread operator to get all the other arguments
我们正在使用传播运算符获取所有其他参数

Now let's define purchaseItem.

现在让我们定义purchaseItem

reduce is a higher-order function. Purchase item receives a bunch of items and they are composed one by one
reduce是一个高阶函数。 购买物料收到一堆物料,它们是一个接一个地组成的

Here we've built our own compose function that allows us to enter any number of parameters that we want into purchase item. Now we can compose these functions and act over the data we receive.

在这里,我们构建了自己的compose函数,该函数允许我们在购买商品中输入任意数量的参数。 现在,我们可以组合这些功能,并对收到的数据进行处理。

  1. Add Item to cart.

    将项目添加到购物车

We are copying the prev cart array so we don't mutate data. We are passing the item we are buying
我们正在复制上一个购物车数组,因此我们不会对数据进行突变。 我们正在传递我们要购买的物品

2.报税 (2. Apply Tax)

If we run this we see that the price of the laptop went up from 200 to 260. We successfully applied a tax
如果执行此操作,我们会发现笔记本电脑的价格从200升至260。我们成功征收了税款

买东西 (Buy Item)

Here we want to move the cart item to purchases

在这里,我们要将购物车商品移至购买

空购物车 (Empty cart)

So now that Kim has purchased her item, we want to empty that cart

因此,既然金已经购买了她的物品,我们想清空该购物车

Kim has just purchased her first laptop.

Kim刚购买了她的第一台笔记本电脑。

Everything just works like a factory. And if we want to add new functionality such as upgrade Kim’s status, the rest of the code doesn't really care about that — we can just create a new function and just add it here.

一切就像工厂一样运作。 And if we want to add new functionality such as upgrade Kim’s status, the rest of the code doesn't really care about that — we can just create a new function and just add it here.

That's the beauty of functional programming.

That's the beauty of functional programming.

It’s the idea that we are building these small comparable functions that are each worried about their own world. So that whenever bugs happen, as long as they are tested well, it's most likely that the bug is in a place where we might have state. The rest of the functions are pure.

It's the idea that we are building these small comparable functions that are each worried about their own world. So that whenever bugs happen, as long as they are tested well, it's most likely that the bug is in a place where we might have state. The rest of the functions are pure.

But here is the exciting part that makes functional programming so interesting. We can playback history as well.

But here is the exciting part that makes functional programming so interesting. We can playback history as well.

As a retailer, you want to keep track of your data. You want to know what users did. So you need a way to figure out what happened — perhaps logs of what the user might have done that may have resulted in an error.

As a retailer, you want to keep track of your data. You want to know what users did. So you need a way to figure out what happened — perhaps logs of what the user might have done that may have resulted in an error.

Using our functional programming paradigm, we have the ability to travel back and forth through time.We can have a history variable that we can fill up at every stage.

Using our functional programming paradigm, we have the ability to travel back and forth through time.We can have a history variable that we can fill up at every stage.

let amazonHistory = [];

let amazonHistory = [];

Now every time we do something, we want to add to this history.

Now every time we do something, we want to add to this history.

addItemToCart, we are pushing the user’s current state.addItemToCart, we are pushing the user's current state.

So that when I run amazonHistory, I have the entire history of Kim and what she did. We can go back in time now and see where Kim made her purchases.

So that when I run amazonHistory, I have the entire history of Kim and what she did. We can go back in time now and see where Kim made her purchases.

Maybe now Amazon can create new functions like getUserState() or go back in history() or goforward(). The possibilities are endless.

Maybe now Amazon can create new functions like getUserState() or go back in history() or goforward(). 可能性是无止境。

And although we are modifying state with amazonHistory, remember we can’t have pure functions alone. At some point, we do have to mutate data. The idea here with functional programming is to minimize those mutations.

And although we are modifying state with amazonHistory , remember we can't have pure functions alone. At some point, we do have to mutate data. The idea here with functional programming is to minimize those mutations.

管 (Pipe)

Remember compose, we go from right to left. If you prefer reading from left to right, you just change compose to pipe and just change g into f and f into g.

Remember compose , we go from right to left. If you prefer reading from left to right, you just change compose to pipe and just change g into f and f into g .

We will have to change the orders of the functions as well in the opposite direction. You can choose pipe and compose based on what you like.

We will have to change the orders of the functions as well in the opposite direction. You can choose pipe and compose based on what you like.

结论 (Conclusion)

Functional programming gives us this idea of a pure function; and functions are useful because we limit repetitions. The beauty is that now every time we use a function, we can reuse it somewhere else.

Functional programming gives us this idea of a pure function; and functions are useful because we limit repetitions. The beauty is that now every time we use a function, we can reuse it somewhere else.

Functional programming lays the foundation for creating reusable code. We can move pieces of functions around to do different things based on our needs.

Functional programming lays the foundation for creating reusable code. We can move pieces of functions around to do different things based on our needs.

Functional programming lays the foundation for creating reusable code. We can move pieces of functions around to do different things based on our needs.

Functional programming lays the foundation for creating reusable code. We can move pieces of functions around to do different things based on our needs.

And although functional programming has different concepts than OOP, at the end of the day, the goal is still the same; we want our code to be:

And although functional programming has different concepts than OOP, at the end of the day, the goal is still the same; we want our code to be:

  1. Clear + UnderstandableClear + Understandable
  2. Easy to extendEasy to extend
  3. Easy to maintain易于维护
  4. Memory efficientMemory efficient
  5. DRYDRY

Composition vs Inheritance (Composition vs Inheritance)

Inheritance is a superclass that is extended to smaller pieces that add or overwrite things.

Inheritance is a superclass that is extended to smaller pieces that add or overwrite things.

Here Elf uses inheritance by using “class extends “
Here Elf uses inheritance by using “class extends “

Composition on the other hand is when we use smaller pieces to create something bigger. We compose functions to act on data differently.

Composition on the other hand is when we use smaller pieces to create something bigger. We compose functions to act on data differently.

Let's see how composition can solve some of the problems that come with inheritance. Keep in mind that the idea is not to pick one over the other.

Let's see how composition can solve some of the problems that come with inheritance. Keep in mind that the idea is not to pick one over the other.

You can use both.

You can use both.

Drawbacks of inheritance.With inheritance, code is structured as what is vs what it has in functional programming.

Drawbacks of inheritance. With inheritance, code is structured as what is vs what it has in functional programming.

With classes, we say that a class will have data, properties, and methods that act upon that data.

With classes, we say that a class will have data, properties, and methods that act upon that data.

But when we define things as what they are, it becomes very hard to be able to change them. With inheritance, we are assuming no change yet things change all the time.

But when we define things as what they are , it becomes very hard to be able to change them. With inheritance, we are assuming no change yet things change all the time.

For example, let's say that from the above example, the character needs to have a sleep method added to it. Now all the classes that extend from character will have the sleep method even though they don’t necessarily need it.

For example, let's say that from the above example, the character needs to have a sleep method added to it. Now all the classes that extend from character will have the sleep method even though they don't necessarily need it.

Tight coupling problem (Tight coupling problem)

With a parent class and a child class, the coupling is very tight.

With a parent class and a child class, the coupling is very tight.

Its the opposite of reusable modular code. Making a small change to a class has a rippling effect on all its subclasses and this tends to break things.

Its the opposite of reusable modular code. Making a small change to a class has a rippling effect on all its subclasses and this tends to break things.

So a tightly coupled inheritance where you can change things in one place and will have rippling effects to all the other things can be a benefit where you keep your code DRY but it can also cause a lot of problems.

So a tightly coupled inheritance where you can change things in one place and will have rippling effects to all the other things can be a benefit where you keep your code DRY but it can also cause a lot of problems.

With dependencies, if you change something on a class, you have to make sure that it doesn't break anything in its subclasses because they are using inheritance.

With dependencies, if you change something on a class, you have to make sure that it doesn't break anything in its subclasses because they are using inheritance.

Fragile base class problem (Fragile base class problem)

Because the base class changes all subclasses, this can be very fragile. It can break our code down the path.

Because the base class changes all subclasses, this can be very fragile. It can break our code down the path.

“‘fragile’ because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class”.

“'fragile' because seemingly safe modifications to a base class, when inherited by the derived classes , may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class”.

Hierarchy problem (Hierarchy problem)

If there were two Elves — boss Elf and Junior Elf and the junior elf inherits from a boss elf. The problem with hierarchy is that now what if the junior elf is higher up in hierarchy for some reason than the boss elf?

If there were two Elves — boss Elf and Junior Elf and the junior elf inherits from a boss elf. The problem with hierarchy is that now what if the junior elf is higher up in hierarchy for some reason than the boss elf?

And if we have more methods it means the junior elf is also going to inherit all the methods that it doesn't need. This is also know as the classic gorilla banana problem.

And if we have more methods it means the junior elf is also going to inherit all the methods that it doesn't need. This is also know as the classic gorilla banana problem.

So how can we fix some of these bad inheritance principles with composition?

So how can we fix some of these bad inheritance principles with composition?

For starters, we can remove all the methods and compose them separately.

For starters, we can remove all the methods and compose them separately.

Here we are saying that these are the abilities that the Elf has. We have the bearest Elf character possible and we can continue adding abilities to it.

Here we are saying that these are the abilities that the Elf has. We have the bearest Elf character possible and we can continue adding abilities to it.

We are turning the inheritance model from what an Elf is to what an Elf does. By having a base Elf, we give the Elf abilities through things like getAttack() which uses functions to add to the character object different abilities. Now we can compose these small little pieces of functionality to describe our character.

We are turning the inheritance model from what an Elf is to what an Elf does. By having a base Elf, we give the Elf abilities through things like getAttack() which uses functions to add to the character object different abilities. Now we can compose these small little pieces of functionality to describe our character.

Also here state is not internal; getAttack simply gets the character state and returns it, same with Elf.

Also here state is not internal; getAttack simply gets the character state and returns it, same with Elf.

So to review, (So to review,)

Inheritance is a superclass that is extended to smaller pieces that add or overwrite things. And although you can be very careful with it and make sure that the base class is very general, so that we don't overload our subclasses, it can easily get out of hand as we go deeper and deeper down the inheritance chain.

Inheritance is a superclass that is extended to smaller pieces that add or overwrite things. And although you can be very careful with it and make sure that the base class is very general, so that we don't overload our subclasses, it can easily get out of hand as we go deeper and deeper down the inheritance chain.

And once we need to change something, it becomes really difficult. On the other hand, composition is about smaller pieces that are combined to create something bigger. We combine these boxes based on what we need to create our desired output.

And once we need to change something, it becomes really difficult. On the other hand, composition is about smaller pieces that are combined to create something bigger. We combine these boxes based on what we need to create our desired output.

And if we need to add something later on, we just add another puzzle by composing things together or even remove them if we don't need them anymore.

And if we need to add something later on, we just add another puzzle by composing things together or even remove them if we don't need them anymore.

So arguably composition is a better solution long term than inheritance but this doesn't mean that inheritance is always bad. There are ways that you can still write great programs with inheritance but with problems that might come up in the future especially with so many unknowns, it becomes really difficult.

So arguably composition is a better solution long term than inheritance but this doesn't mean that inheritance is always bad. There are ways that you can still write great programs with inheritance but with problems that might come up in the future especially with so many unknowns, it becomes really difficult.

Composition will help us create code that is more stable as well as easier to change in the future — its simply a better tool to use when creating software.

Composition will help us create code that is more stable as well as easier to change in the future — its simply a better tool to use when creating software.

A programming paradigm is writing code compliant with a specific set of rules. For example, organizing code into units would be called OOP and avoiding side effects as well as writing pure functions would be called FP.

A programming paradigm is writing code compliant with a specific set of rules. For example, organizing code into units would be called OOP and avoiding side effects as well as writing pure functions would be called FP.

In OOP, an object is a box containing information and operations that are supposed to refer to the same concept or grouping it as an object. These pieces of information inside the object are called attributes or state and the operations that can happen on the state are known as methods.

In OOP, an object is a box containing information and operations that are supposed to refer to the same concept or grouping it as an object. These pieces of information inside the object are called attributes or state and the operations that can happen on the state are known as methods.

In functional programming, the code is essentially a combination of functions and data is immutable; this leads to writing programs with no side effects.

In functional programming, the code is essentially a combination of functions and data is immutable; this leads to writing programs with no side effects.

A pure function cannot change the outside world and the output value of a function depends on the given arguments. This allows functional programming to have real control over the program flow.

A pure function cannot change the outside world and the output value of a function depends on the given arguments. This allows functional programming to have real control over the program flow.

In functional programming, functions are first-class citizens whereas in OOP, objects are first-class citizens.

In functional programming, functions are first-class citizens whereas in OOP, objects are first-class citizens.

We also saw the pillars of each of these paradigms. In OOP, we had Abstraction, Encapsulation, where it allows us to encapsulate ideas that are related together in objects. We hide irrelevant data from the user. We learned about inheritance and polymorphism.

We also saw the pillars of each of these paradigms. In OOP, we had Abstraction, Encapsulation, where it allows us to encapsulate ideas that are related together in objects. We hide irrelevant data from the user. We learned about inheritance and polymorphism.

In FP, we saw that it's all about the idea of pure functions and composing functions to act upon that data.

In FP, we saw that it's all about the idea of pure functions and composing functions to act upon that data.

Both these paradigms have been around since the 70s.

Both these paradigms have been around since the 70s.

OOP is very common in languages such as C sharp, Python, Java, and FP in languages such as closure and Huskel.

OOP is very common in languages such as C sharp, Python, Java, and FP in languages such as closure and Huskel.

But at the end of the day, we are not choosing one over the other. All of them are good in their own ways. They are simply different approaches to the same problem.

But at the end of the day, we are not choosing one over the other. All of them are good in their own ways. They are simply different approaches to the same problem.

Although some languages prefer one over the other in terms of programming paradigms, however, languages like Javascript allow you to do both.

Although some languages prefer one over the other in terms of programming paradigms, however, languages like Javascript allow you to do both.

The advantage of each paradigm is in the way you model your algorithm and data structures, the choice is simply what makes more sense for your project

The advantage of each paradigm is in the way you model your algorithm and data structures, the choice is simply what makes more sense for your project

Key differences (Key differences)

FP is all about performing many different operations for which the data is fixed.

FP is all about performing many different operations for which the data is fixed.

OOP is about few operations on common data.

OOP is about few operations on common data.

In FP, we don't modify state.

In FP, we don't modify state.

OOP is very stateful.

OOP is very stateful.

FP functions are pure; there are no side effects. The functions we write don't make an impact on the code that is running outside of that function.

FP functions are pure; there are no side effects. The functions we write don't make an impact on the code that is running outside of that function.

In OOP there are side effects; methods manipulate our internal state.

In OOP there are side effects; methods manipulate our internal state.

FP is more declarative. It's about what we want to be doing

FP is more declarative. It's about what we want to be doing

OOP is about how we want it to be done which is more imperative.

OOP is about how we want it to be done which is more imperative.

So when should you use one over the other? (So when should you use one over the other?)

FP is quite good at processing data for large applications. If you are analyzing user data, maybe using it for a machine learning model, Functional programming works well for high performance in processors and because you can run it on multiple processors.

FP is quite good at processing data for large applications. If you are analyzing user data, maybe using it for a machine learning model, Functional programming works well for high performance in processors and because you can run it on multiple processors.

If on the other hand you have many things like characters in a game, with not too many operations, then OOP might be a better solution.

If on the other hand you have many things like characters in a game, with not too many operations, then OOP might be a better solution.

But you can use the ideas from both of these to write your code. For example, the react javascript framework, uses both classes and pure functions

But you can use the ideas from both of these to write your code. For example, the react javascript framework , uses both classes and pure functions

In all programs, there are two primary components:The data and behavior.

In all programs, there are two primary components:The data and behavior.

OOP says, bring together the data and the behavior in a single location called object or class. It’s gonna allow us to understand our program easier and be more organized.

OOP says, bring together the data and the behavior in a single location called object or class. It's gonna allow us to understand our program easier and be more organized.

Functional programming says that data and behavior and distinctly different things and should be kept separate for clarity.

Functional programming says that data and behavior and distinctly different things and should be kept separate for clarity.

翻译自: https://medium.com/swlh/a-comprehensive-look-at-functional-programming-fp-4a87629ecaed

fp函数式编程


http://www.taodudu.cc/news/show-3105768.html

相关文章:

  • 关于FP的一些概念
  • 全免费 个人电脑部署私有云电脑系统 特别适合初创团队和工作室
  • 本地电脑怎么连接mysql_本地电脑无法连接到MySQL
  • 电脑公司特别版8.5出现 fastfat.sys文件不正确及蓝屏错误的原因之一
  • GhostXP_SP2电脑公司特别版_v4.1
  • 日志易之配置日志内容黑名单
  • 易经-乾坤易之门
  • V2X前装量产的现状与挑战 | 车联网百家谈
  • 易语言连接mysql学习_[易语言]连接MYSQL数据库学习
  • 易之 - 我是个大师(2014年3月6日)
  • 天下莫柔弱于水,而攻坚强者莫之能胜,以其无以易之。弱之胜强,柔之胜刚,天下莫不知,莫能行……
  • 看百度搜索的变易之道:AI引领的新搜索时代丨Xtecher 观察
  • 运维人必备:日志分析工具日志易之银行业解决方案
  • 日志易之AIX、HP-UNIX小机探针Agent安装步骤
  • 乾坤易之門章
  • 日志易之Agent统一IP地址开通多个端口
  • 易之 - 我是个算命先生(2014年3月23日)
  • 用linux系统做数字钟,大强学易之易语言实例:简单的易语言桌面电子时钟
  • 上海帖易之易度文档管理
  • 易之城
  • 易之开篇
  • 总规、控规、修规、概念性规划之间的关系
  • 中小型网络系统总体规划与设计方法(一)
  • 【特色小镇】智慧小镇:小镇建设总体规划方案
  • 总体规划,循序渐进,分步实施
  • 【空间规划符号库】国土空间规划_制图规范+制图样式
  • 六轴机械臂DIY(一)机械臂DIY总体规划
  • 国土空间总体规划编制之基期数据转换工具(免费)
  • 土地利用总体规划表现形式
  • 智慧校园总体规划方案

fp函数式编程_全面了解函数式编程(FP)相关推荐

  1. 学python编程_少儿学Python编程的一些思考

    自从孩子上了初中,孩子妈就开始盯着各种真假难辨的中考.高考新政传言.当她从铺天盖地的少儿编程广告里获悉,编程将纳入中考,高考范围,并且2018年高考,多个省份的数学卷甚至都出现了编程题时,就变得异常兴 ...

  2. 华兴数控g71外圆循环编程_数控车床加工编程典型实例分析(西门子802S数控系统)...

    这是一篇带有教学色彩的习作,文章对数控编程的方式和步骤进行了简明的阐述,并针对一个典型零件的数控车削加工给出了一套程序.程序是以西门子802S数控系统为例编写的. 数控机床是一种技术密集度及自动化程度 ...

  3. python青少年编程_机器人Python青少年编程开发实例

    章 打开极客之门 1.1 TurnipBit是什么 1.2 从拼插编程开始 1.3 做个真正的程序员 1.3.1 什么Python 1.3.2 面向硬件的MicroPython 1.3.3 支持Mic ...

  4. redux 函数式组件_如何从函数式编程的角度学习Redux

    redux 函数式组件 Discover Functional JavaScript was named one of the best new Functional Programming book ...

  5. 换硬币c语言编程_如何才能成为编程高手?别人都不告诉你的东西,我来说给你听...

    在IT行业摸爬滚打十几年的应该知道,下面简单说说关于编程需要掌握的技术与相关知识.很多人感觉编程很难.很多人问我,我英语不好,数学不好能做编程吗? 我非常肯定的说,能做编程.编程的领域很广泛.细分出来 ...

  6. 初学者怎么自学python编程_怎样自学python编程?从零开始学习python,400集免费教程!...

    作为小白,在学习Python的时候,必然会走一定的弯路,有人在弯路上走丢了,有人走出了弯路.我就是属于还未走出弯路的同学,所以我想谈谈我的Python学习之路. 01先了解一下什么是python‍? ...

  7. ai人工智能编程_从人工智能动态编程:Q学习

    ai人工智能编程 A failure is not always a mistake, it may simply be the best one can do under the circumsta ...

  8. python数据结构编程_写给Python编程高手之 数据结构

    python视频教程栏目介绍Python编程需要注意的关键点. 如何在列表,字典,集合中根据条件筛选数据 案例:如何在下列列表data中筛选出大于0的数data = [1, -1, 2, 3, 4, ...

  9. python实例编程_浅谈如何编程Python3——Python实例(3)

    浅谈如何编程Python3--Python实例(3) # 测试实例一 print("测试实例一") str= "runoob.com"print(str.isa ...

最新文章

  1. RecyclerView显示加载多种布局的原理
  2. hive分区用2个字段有何限制_关于Hive使用动态分区插入数据详解
  3. underscore 系列之防冲突与 Utility Functions
  4. IT人员健康信号之舌苔
  5. boost::lexical_cast模块测试 Source 是否不可复制
  6. 去除bootstrap中input输入框的蓝色光
  7. Codeforces Beta Round #11 B. Jumping Jack 思维
  8. plot画分段函数_python画图函数大全
  9. 视频参数(流媒体系统,封装格式,视频编码,音频编码,播放器)对比
  10. (pytorch-深度学习)双向循环神经网络
  11. 费诺码设计matlab,费诺编码的matlab实现.doc
  12. 4 form j1 w 如何填写_设计必备方法,如何通过数据优化设计?
  13. [迁移] Luac的使用
  14. VMware虚拟机XP系统安装图文教程
  15. java实现PDF转tif格式并且设置颜色和dpi
  16. VS2013好用的插件
  17. ANS.1的基础总结
  18. css 如何实现文本竖排、横排展示
  19. 求最大公因数的两种方法(高效方法)
  20. 华中科技大学计算机徐永兵,华中科技大学计算机学院导师及科研方向.doc

热门文章

  1. 电脑启动项和系统引导项设置
  2. DevOps工具链学习——相关工具知多少
  3. 前端使用lottie-web,使用AE到处的JSON动画贴心教程
  4. 轻松洁净地面,还能自动清洗烘干拖布,只需一台追觅扫拖机器人
  5. oracle 取季度末,根据季度及年度值,查季度末最后一天
  6. 语音识别开源库 FastARS 移植到GEC6818开发版
  7. 网络应用技术之网络层
  8. 解决error: (-210:Unsupported format or combination of formats) [Start]FindContours supports only CV_8U
  9. Maya角色手指动作约束方案
  10. Pytorch之Bert文本分类(一)