函数式编程

主要的编程范式有三种:命令式编程,声明式编程和函数式编程。

命令式编程:

命令式编程的主要思想是关注计算机执行的步骤,即一步一步告诉计算机先做什么再做什么。

比如:如果你想在一个数字集合 collection(变量名) 中筛选大于 5 的数字,你需要这样告诉计算机:

第一步,创建一个存储结果的集合变量 results;

第二步,遍历这个数字集合 collection;

第三步:一个一个地判断每个数字是不是大于 5,如果是就将这个数字添加到结果集合变量 results 中。

很明显,这个样子的代码是很常见的一种,不管你用的是 C, C++ 还是 C#, Java, Javascript, BASIC, Python, Ruby 等等,你都可以以这个方式写。


声明式编程:

声明式编程是以数据结构的形式来表达程序执行的逻辑。它的主要思想是告诉计算机应该做什么,但不指定具体要怎么做。

SQL 语句就是最明显的一种声明式编程的例子,例如:

SELECT*FROM collection WHERE num>5

除了 SQL,网页编程中用到的 HTML 和 CSS 也都属于声明式编程。

通过观察声明式编程的代码我们可以发现它有一个特点是它不需要创建变量用来存储数据。


函数式编程:

“函数式编程”, 又称泛函编程, 是一种”编程范式”(programming paradigm),也就是如何编写程序的方法论,和指令式编程相比,函数式编程的思维方式更加注重函数的计算。函数式编程和声明式编程是有所关联的,因为他们思想是一致的:即只关注做什么而不是怎么做。但函数式编程不仅仅局限于声明式编程。它的主要思想是把问题的解决方案写成一系列嵌套的函数调用。

函数式编程最重要的特点是“函数第一位”,即函数可以出现在任何地方,比如你可以把函数作为参数传递给另一个函数,不仅如此你还可以将函数作为返回值。大部分常见的编程语言一半都已经提供了对这种编程方式的支持,比如 JavaScript,再有 C# 中的 LINQ 和 Java 中的 Lambda 和闭包的概念。

使用指令式编程时,当情况变得更加复杂,表达式的写法会遇到几个问题:表意不明显,逐渐变得难以维护复用性差,会产生更多的代码量会产生很多中间变量。这个时候使用函数式编程的优势就提现出来了:

函数式编程的优点

1. 代码简洁,开发快速

函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。

// 数组中每个单词,首字母大写

// 一般写法

const arr = ['apple','pen','apple-pen'];

for(const i in arr){

const c = arr[i][0];

arr[i] = c.toUpperCase() + arr[i].slice(1);

}

console.log(arr);

// 函数式写法一

function upperFirst(word){

returnword[0].toUpperCase() + word.slice(1);

}

function wordToUpperCase(arr){

returnarr.map(upperFirst);

}

console.log(wordToUpperCase(['apple','pen','apple-pen']));

// 函数式写法二

console.log(arr.map(['apple','pen','apple-pen'], word => word[0].toUpperCase() + word.slice(1)));

2. 接近自然语言,易于理解

函数式编程的自由度很高,可以写出很接近自然语言的代码。

将表达式(1 + 2) * 3 - 4,写成函数式语言:subtract(multiply(add(1,2), 3), 4)

对它进行变形,不难得到另一种写法:add(1,2).multiply(3).subtract(4)

这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:

merge([1,2],[3,4]).sort().search("2")

因此,函数式编程的代码更容易理解。

3. 更方便的代码管理

函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。因此,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing)和除错(debugging),以及模块化组合。


函数编程的一些基本特点包括:

1. 函数是”第一等公民”:

    函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

2. 高阶函数(Higher Order Function):

    将函数作为参数,或者是可以将函数作为返回值的函数。比如我们平常用到的回调函数.

3. 函数柯里化(Currying):

    把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数。

其过程就是消化一个参数,然后生成一个新的函数,剩余的参数作为新函数的参数。

// 柯里化之前

function add(x, y) {

    return x + y;

}

add(1, 2) // 3

// 柯里化之后

function addX(y) {

    return function (x) {

        return x + y;

    };

}

addX(2)(1) // 3

4. 懒惰计算(lazy evaluation):

    在惰性计算中,表达式不是在绑定到变量时立即计算,而是在求值程序需要产生表达式的值时进行计算。

5. 引用透明性:

指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

6. 没有副作用:

    意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。

7. 纯函数:

    - 其结果只能从它的参数的值来计算 

    - 不能依赖于能被外部操作改变的数据 

    - 不能改变外部状态


函数式编程思维在我们工作中的体现

    1.map/reduce/filter方法

    传入一个函数作为参数,返回一个新的数组,不对原来的数组进行修改,不使用中间变量,没有副作用。

    2.闭包

    闭包的主要用途就是可以定义一些作用域局限的持久化变量,这些变量可以用来做缓存或者计算的中间量等等。

    下面的例子是一个简单的缓存工具的实现,匿名函数创造了一个闭包,使得 store 对象 ,一直可以被引用,不会被回收。

// 简单的缓存工具

const cache = (function() {

    const store = {};

    return {

        get(key) {

            return store[key];

        },

        set(key, val) {

            store[key] = val;

        }

    }

}());

cache.set('a', 1);

cache.get('a'); // 1

    3.链式优化

    比如回调函数和promise函数

// 优化写法 (loadsh 的链式写法)

constutils = {

  chain(a) {

this._temp = a;

returnthis;

  },

  sum(b) {

this._temp += b;

returnthis;

  },

  sub(b) {

this._temp -= b;

returnthis;

  },

  value() {

const_temp =this._temp;

this._temp =undefined;

return_temp;

  }

};

console.log(utils.chain(1).sum(2).sum(3).sub(4).value());

4.连续箭头函数

function add(a) {

    return function(b) {

        return a + b

    }

}

var add3 = add(3)

add3(4) === 3 + 4 //true

add 函数 在 es6 里的写法等价为

let add = a => b => a + b

add(3)(4)


参考文章:

https://github.com/EasyKotlin/chapter8_fp

http://taobaofed.org/blog/2017/03/16/javascript-functional-programing/

https://www.cnblogs.com/sirkevin/p/8283110.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容