函数式编程你需要知道这些(一、函数)

函数式编程浅谈——函数

函数式编程是一种思想,可能你一直在沿用这种思想,但是,你能说清楚,它到底是什么吗?

瞧一瞧~

目录

前言

  • 最主要的特征是,函数是第一等公民
  • 只有纯的、没有副作用的函数,才是合格的函数(即应该是功能型而不是需求型)

中心思想: 为什么函数式编程要求函数必须是纯的,不能有副作用?因为它是一种数学运算,原始目的就是求值,不做其他事情,否则就无法满足函数运算法则了。

一、一等公民的函数

当我们说函数是“一等公民”的时候,实际上说的是它们和其他对象都一样,你可以像对待任何其他数据类型一样对待它们——把它们存在数组里,当作参数传递,赋值给变量…等等。

先来一个例子预热一下:

const hi = name => `Hi ${name}`;
const greeting = name => hi(name); //感觉我也写过...

greeting 只不过是转了个身然后以相同的参数调用了 hi 函数而已,因此我们可以这么写:

const greeting = hi;
greeting("times"); // "Hi times"

用一个函数把另一个函数包起来,目的仅仅是延迟执行,真的是非常糟糕的编程习惯。(这可维护性密切相关。)

进阶:

const getServerStuff = callback => ajaxCall(json => callback(json));

// 等价于

const getServerStuff = ajaxCall;

以下是上述两种写法等价的原因:(类似数学换算)

原代码 新代码
ajaxCall(json => callback(json)); ajaxCall(callback);
getServerStuff = callback => ajaxCall(callback); getServerStuff = ajaxCall

各位,以上才是写函数的正确方式。看到这里,终于有点开窍了吧。

const BlogController = {
  index(posts) { return Views.index(posts); },
  show(post) { return Views.show(post); },
  create(attrs) { return Db.create(attrs); },
  update(post, attrs) { return Db.update(post, attrs); },
  destroy(post) { return Db.destroy(post); },
};

我们可以把它重写成这样:

const BlogController = {
  index: Views.index,
  show: Views.show,
  create: Db.create,
  update: Db.update,
  destroy: Db.destroy,
};

为何钟爱一等公民?

  • 每次改动将会少得多:
  • 有利于剥离相同的概念

项目中常见的一种造成混淆的原因是,针对同一个概念使用不同的命名。还有通用代码的问题。比如,下面这两个函数做的事情一模一样,但后一个就显得更加通用,可重用性也更高:

const validArticles = articles =>
  articles.filter(article => article !== null && article !== undefined),

// 对未来的项目更友好
const compact = xs => xs.filter(x => x !== null && x !== undefined);

在命名的时候,我们特别容易把自己限定在特定的数据上(本例中是 articles)。这种现象很常见,也是重复造轮子的一大原因。

二、纯(干净)的函数

首先,我们要理清纯函数的概念。

纯函数是这样一种函数:

  • 即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

比如 slice 和 splice,这两个函数的作用类似

  • slice 符合:因为对相同的输入它保证能返回相同的输出。
  • splice 不符合:因为被处理的数组永久地改变了。

让我们来仔细研究一下“副作用”以便加深理解

  • 副作用是在计算结果的过程中,系统状态的一种变化,或者与外部世界进行的可观察的交互。
  • 副作用可能包含,但不限于:
    • 更改文件系统
    • 往数据库插入记录
    • 发送一个 http 请求
    • 可变数据
    • 打印/log
    • 获取用户输入
    • DOM 查询

为何要坚持这种「相同输入得到相同输出」原则

函数是不同数值之间的特殊关系:每一个输入值返回且只返回一个输出值。

换句话说,函数只是两种数值之间的关系:输入和输出。尽管每个输入都只会有一个输出,但不同的输入却可以有相同的输出。下图展示了一个合法的从xy的函数关系;

相反,下面这张图表展示的就不是一种函数关系,因为输入值 5 指向了多个输出:

纯函数就是数学上的函数,而且是函数式编程的全部。使用这些纯函数编程能够带来大量的好处,让我们来看一下为何要不遗余力地保留函数的纯粹性的原因。

我们已经大致了解什么是纯函数了,也看到作为函数式程序员的我们,为何深信纯函数是不同凡响的。从这开始,我们将尽力以纯函数式的方式书写所有的函数。为此我们将需要一些额外的工具(curry)来达成目标,同时也尽量把非纯函数从纯函数代码中分离。

发布了292 篇原创文章 · 获赞 48 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/jbj6568839z/article/details/105267099
今日推荐