函数编程代码例子_使用函数式编程使代码更易于阅读

函数编程代码例子

Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!

“发现功能JavaScript”BookAuthority评为最佳新功能编程书籍之一

Pure functions are easier to read and understand. All the function’s dependencies are in its definition and are therefore easier to see. Pure functions also tend to be small and do one thing. They don’t use this, a constant source of confusion.

纯函数更易于阅读和理解。 所有函数的依赖项都在其定义中,因此更易于查看。 纯函数也往往很小并且只能做一件事。 他们不使用thisthis是不断引起混乱的原因。

链式 (Chaining)

Chaining is a technique used to simplify code where multiple methods are applied to an object one after another.

链接是一种用于简化代码的技术,其中将多个方法一个接一个地应用于一个对象。

Let’s look and compare the two styles: imperative and functional. In the functional style, I use the basic toolbox for list operations filter() and map() . Then I chain them together.

让我们看看并比较两种样式:命令式样式和功能样式。 在功能样式中,我将基本工具箱用于列表操作filter()map() 。 然后,我将它们链接在一起。

I took the case of a collection of tasks. A task has an id, a description (desc) a boolean completed, a type and an assigned user object. The user object has a name property.

我以一系列任务为例。 任务具有id ,描述( desc ),布尔值completedtype和分配的user对象。 用户对象具有name属性。

//Imperative style
let filteredTasks = [];
for(let i=0; i<tasks.length; i++){
    let task = tasks[i];
    if (task.type === "RE" && !task.completed) {
        filteredTasks.push({ ...task, userName: task.user.name });
    }
}

//Functional style
function isPriorityTask(task){
   return task.type === "RE" && !task.completed;
}

function toTaskView(task) {
   return { ...task, userName: task.user.name };
}

let filteredTasks = tasks.filter(isPriorityTask).map(toTaskView);

Notice the callbacks for filter() and map() as pure functions with intention revealing names.

注意filter()map()的回调是具有意图揭示名称的纯函数。

map() transforms a list of values to another list of values using a mapping function.

map()使用映射函数将值列表转换为另一个值列表。

Here is a performance test measuring the difference between the two styles. It seems that the functional approach is 60% slower. When the imperative process finishes in 10 milliseconds, the functional approach will finish in 16 milliseconds. In that case using the imperative loop will be a premature optimization.

这是一项性能测试,用于测量两种样式之间的差异。 看来,功能性方法要慢60%。 当命令式过程在10毫秒内完成时,功能性方法将在16毫秒内完成。 在这种情况下,使用命令式循环将是过早的优化。

无点式 (Point-free style)

In the previous example, I have used the point-free style when composing functions. Point-free is a technique that improves readability by eliminating the unnecessary arguments. Consider the next code:

在前面的示例中,我在编写函数时使用了无点样式。 无点是通过消除不必要的参数来提高可读性的技术。 考虑下一个代码:

tasks.filter(task => isPriorityTask(task)).map(task => toTaskView(task));

In a point-free style it is written without arguments:

以无点样式编写,没有参数:

tasks.filter(isPriorityTask).map(toTaskView);

For more on point-free look at How point-free composition will make you a better functional programmer

有关无点组合的更多信息,请参见无点组合如何使您成为更好的函数式程序员

部分申请 (Partial Application)

Next, I want to look into how we can improve readability and also reuse an existing function. Before doing that, we need a new function in our toolbox.

接下来,我想研究一下如何提高可读性并重用现有功能。 在此之前,我们需要在工具箱中添加一个新功能。

Partial application refers to the process of fixing a number of arguments to a function.

部分应用是指将多个参数固定到函数的过程。

It’s a way to go from generalization to specialization.
这是从泛化到专业化的一种方法。

For partial application we can use the partial() function from a popular library like underscore.js or lodash.js. The bind() method can also do partial application.

对于部分应用程序,我们可以使用来自underscore.jslodash.js之类的流行库中的partial()函数。 bind()方法也可以进行部分应用。

Let’s say we want to refactor the following imperative code to a functional, easier to read, style:

假设我们想将以下命令式代码重构为功能性,易于阅读的样式:

let filteredTasks = [];
for(let i=0; i<tasks.length; i++){
    let task = tasks[i];
    if (task.type === "NC") {
        filteredTasks.push(task);
    }
}

As I said, this time we want to create a generic function that can be used for filtering by any task type. isTaskOfType() is the generic function. The partial() function is used to create a new predicate function isCreateNewContent() that filters by a specific type.

就像我说的,这次我们要创建一个通用函数,该函数可用于按任何任务类型进行过滤。 isTaskOfType()是通用函数。 partial()函数用于创建一个新的谓词函数isCreateNewContent() ,该谓词函数按特定类型进行过滤。

A predicate function is a function that takes one value as input and returns true/false based on whether the value satisfies the condition.

谓词函数是将一个值作为输入并根据该值是否满足条件返回true / false的函数。

function isTaskOfType(type, task){
  return task.type === type;
}

let isCreateNewContent = partial(isTaskOfType, "NC");
let filteredTasks = tasks.filter(isCreateNewContent);

Notice the predicate function. It has a name expressing its intention. When I’m reading tasks.filter(isCreateNewContent) I clearly understand what kind of tasks I’m selecting.

注意谓词功能。 它有一个表达其意图的名称。 当我阅读tasks.filter(isCreateNewContent)我清楚地了解到我选择了哪种tasks

filter() selects values from a list based on a predicate function that decides what values should be kept.

filter() 根据决定要保留哪些值的谓词函数从列表中选择值。

减少 (Reduce)

I will start a new example using a shopping list. Here is how the list may look like:

我将使用购物清单开始一个新示例 。 列表如下所示:

let shoppingList = [
   { name : "orange", units : 2, price : 10, type : "FRT"},
   { name : "lemon", units : 1, price : 15, type : "FRT"},
   { name : "fish", units : 0.5, price : 30, type : "MET"}
];

I will compute the total price and the price for fruits only. Below is the imperative style:

我将只计算总价格和水果价格。 下面是命令式:

let totalPrice = 0, fruitsPrice = 0;
for(let i=0; i<shoppingList.length; i++){
   let line = shoppingList[i];
   totalPrice += line.units * line.price;
   if (line.type === "FRT") {
       fruitsPrice += line.units * line.price;
   }
}

Taking the functional approach in this case will require the use of reduce() to compute the total price.

在这种情况下采用功能性方法将需要使用reduce()来计算总价。

reduce() reduces a list of values to one value.

reduce() 将值列表简化为一个值。

As we did before, we create new functions for the required callbacks and give them intention revealing names : addPrice() and areFruits().

和以前一样,我们为所需的回调创建新函数,并为其赋予意图的揭示名称: addPrice()areFruits()

function addPrice(totalPrice, line){
   return totalPrice + (line.units * line.price);
}

function areFruits(line){
   return line.type === "FRT";
}

let totalPrice = shoppingList.reduce(addPrice,0);
let fruitsPrice = shoppingList.filter(areFruits).reduce(addPrice,0);

结论 (Conclusion)

Pure functions are easier to read and reason about.

纯函数更易于阅读和推理。

Functional Programming will break list operations in steps like: filter, map, reduce, sort. At the same time, it will require to define new pure small functions to support those operations.

函数式编程将按以下步骤中断列表操作:过滤,映射,缩小,排序。 同时,将需要定义新的纯小的函数来支持这些操作。

Combining Functional Programming with the practice of giving intention revealing names greatly improves the readability of the code.

将函数式编程与提供意图揭示名称的做法相结合,可以大大提高代码的可读性。

Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!

发现功能JavaScript被称为 BookAuthority最好的新功能编程书籍

For more on applying functional programming techniques in React take a look at Functional React.

有关在React中应用函数式编程技术的更多信息,请查看 Functional React

Learn functional React, in a project-based way, with Functional Architecture with React and Redux.

通过带有React和Redux的功能架构 ,以基于项目的方式学习功能性React

Follow on Twitter

在Twitter上关注

翻译自: https://www.freecodecamp.org/news/make-your-code-easier-to-read-with-functional-programming-94fb8cc69f9d/

函数编程代码例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值