概述

PointFree是一种编程风格,他的具体实现是函数的组合,他更抽象一些。

PointFree的概念是,我们可以把数据处理的过程定义成与数据无关的合成作用,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

整个这句话比较绕口,我们可以把这句话提炼成三点。

1.第一点: 不需要指明处理的数据

2.第二点: 只需要合成运算的过程

3.第三点: 在合成运算的时候需要一些辅助的基本运算函数。

使用函数组合在处理问题的时候,其实就是一种PointFree模式,比如下面的这个案例,在这个案例中我们先把一些基本的运算合成为一个函数,而在这个过程中是没有指明要处理的数据的,这就是PointFree模式。

const _ = require('lodash');
const fp = require('lodash/fp');

const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.split(' '))

接下来我们通过案例来演示一下,非PointFree模式和PointFree模式。

我们先来看一下非PointFree模式,假设我们要把Hello World转换为hello_world这样的形式。

按照我们传统的思维方式,我们会先定义一个函数,来接收一个我们要处理的数据,接着我们在这个函数里面对我们的数据进行处理,得到我们想要的结果,这是非PointFree模式。

function f (word) {
    return word.toLowerCase().replace(/\s+/, '_');
}
f('Hello World')

而我们如果使用PointFree模式来解决这个问题的话,我们首先会定义一些基本的运算函数,然后把他们何成为一个新的函数,而在合成的过程中我们不需要指明我们需要处理的数据。

那我们来回顾一下函数式编程的核心,其实就是把运算过程抽象成函数。PointFree模式就是把我们抽象出来的函数再合成为一个新的函数,而这个合成的过程其实又是一个抽象的过程。在这个抽象的过程中我们依然是不需要关心数据的。

下面我们使用PointFree模式来实现一下上面的案例。

我们首先来分析一下,我们可以把这个字符串先转换成小写,然后再把空格替换成下划线,那如果中间的空格比较多,我们应该使用正则来匹配。所以在这个过程中我们要用到两个方法,一个是转换成小写的方法,一个是字符串替换的方法。

const fp = require('lodash/fp');
fp.toLower; // 转换为小写的方法
fp.replace; // 字符串替换的方法

因为我们要使用PointFree的方式来处理,所以我们可以把这两个过程合并成一个新的函数,而在这个过程中我们是不需要指明我们所需要的数据的。

我们先来导入lodash的fp模块,接着我们就要去合成函数,我们先定义一个f等于fp中的flowRight组合函数。

那在函数组合的时候,首先我们要处理的是转换小写的运算,我们传入fp.toLower

const fp = require('lodash/fp');
const f = fp.flowRight(fp.toLower);

然后我们再使用fp.replace替换,因为flowRight是从右向左执行的,所以我们要写在fp.toLower前面。

我们知道fp.replace这个方法是有三个参数的, 第一个参数是匹配的模式,也就是被替换的值,可以是正则表达式,第二个参数是替换成的内容,第三个参数是要处理的字符串。

fp中提供的方法都是已经被柯里化的,所以我们可以只传部分参数他会返回一个新的函数。

那这里我们调用fp.replace的时候就传入两个参数,第一个是匹配空白的正则表达式/\s+/g, 第二个参数是下划线_, 当我们只传两个参数的时候他会返回一个新的函数,新函数会接收要处理的数据,所以这里函数组合就写完了。

const fp = require('lodash/fp');
const f = fp.flowRight(fp.replace(/\s+/g, '_'), fp.toLower);

f('Hello World'); // hello_world

我们可以发现,当我们在函数组合的过程中,我们是不需要去指明我们要处理的数据的。

至此,PointFree的模式我们就演示完了。