函数式编程

函数式编程不是用函数来编程,旨在将复杂的函数符合成简单的函数。

1.函数是一等公民。所谓”第一等公民”(first class),指的是函数 与其他数据类型一样,处于平等地位,可以赋值给其他变量,也 可以作为参数,传入另一个函数,或者作为别的函数的返回值。

2..不可改变量。在函数式编程中,我们通常理解的变量在函数式 编程中也被函数代替了:在函数式编程中变量仅仅代表某个表达 式。这里所说的’变量’是不能被修改的。所有的变量只能被赋一次 初值 。

3.map & reduce他们是常用的函数式编程的方法。

函数式编程常用核心概念:

1.纯函数

  对于相同的输入,永远会得到相同的输出,而且没有任 何可观察的副作用,也不依赖外部环境的状态。

var x = [1,2,3,4,5,6];
console.log(x.slice(0,3));  //[1,2,3]
console.log(x.slice(0,3));  //[1,2,3]
console.log(x.splice(0,3)); //[1,2,3]
console.log(x.splice(0,3)); //[4,5,6]

对于上述例子,slice就是一个纯函数,而splice就不是,因为两次得到的结果不同。

//不纯的
var min = 18;
var checkage = age => age>min;

//纯的
var checkage = age => age>18;

上面的例子,不纯是因为依赖了外部变量min。
  但是上面的纯函数有个问题就是18被写死了,这样函数的扩展性就比较差,下面我们用柯里化来解决这个问题。

2.函数的柯里化

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

对于前面说的问题,现用柯里化解决

var checkage = min => (age => age>min);
var checkage18 = checkage(18);
console.log(checkage18(20));    //true

// 上面的函数等价于
function checkage(min){
   return function(age){
       return age>min
    }
}
console.log(checkage(18)(20));

  事实上柯里化是一种“预加载”函数的方法,通过传递较少的参数, 得到一个已经记住了这些参数的新函数,某种意义上讲,这是一种 对参数的“缓存”,是一种非常高效的编写函数的方法。

3.函数组合

  纯函数以及如何把它柯里化写出的洋葱代码 h(g(f(x))), 为了解决函数嵌套的问题,我们需要用到“函数组合”:

const compose = (f,g) => (x =>f(g(x)));
var first = arr => arr[0];
var reverse = arr => arr.reverse();
var last = compose(first,reverse);
console.log(last([1,2,3,4,5]));    //5

//第一行代码等价于
function compose(f,g){
    return function(x){
        return f(g(x));
    }
}
4.point Free

  point Free把一些对象自带的方法转化成纯函数,不要命名转瞬即逝 的中间变量。

const compose = (f,g) => (x => f(g(x)));
var toUpperCase = word =>word.toUpperCase();
var split = x => (str => str.split(x));

var f = compose(split(''),toUpperCase);
console.log(f("abcd efgh"));    // ["A", "B", "C", "D", " ", "E", "F", "G", "H"]
5.声明式与命令式代码

   命令式代码的意思就是,我们通过编写一条又一条指令去让计算 机执行一些动作,这其中一般都会涉及到很多繁杂的细节。而声 明式就要优雅很多了,我们通过写表达式的方式来声明我们想干 什么,而不是通过一步一步的指示。

 //命令式 
let ceos= [];
for(var i = 0; i < companies.length; i++){   
    ceos.push(companies[i].ceo) 
} 

//声明式 
let ceos = companies.map(c => c.ceo);

   函数式编程的一个明显的好处就是这种声明式的代码,对 于无副作用的纯函数,我们完全可以不考虑函数内部是如何实 现的,专注于编写业务代码。优化代码时,目光只需要集中在 这些稳定坚固的函数内部即可。
   相反,不纯的函数式的代码会产生副作用或者依赖外部系 统环境,使用它们的时候总是要考虑这些不干净的副作用。在 复杂的系统中,这对于程序员的心智来说是极大的负担。

6.惰性求值、惰性函数

   在指令式语言中以下代码会按顺序执行,由于每个函数 都有可能改动或者依赖于其外部的状态,因此必须顺序 执行。
  一旦我们接纳了函数式哲学,惰性(或延迟)求值这一技术会变得非常有趣。在讨论并行时已经见过下面的代码片断:

String s1 = somewhatLongOperation1();

String s2 = somewhatLongOperation2();

String s3 = concatenate(s1, s2);

   在一个命令式语言中求值顺序是确定的,因为每个函数都有可能会变更或依赖于外部状态,所以就必须有序的执行这些函数:首先是 somewhatLongOperation1,然后 somewhatLongOperation2,最后 concatenate,在函数式语言里就不尽然了。
   前面提到只要确保没有函数修改或依赖于全局变量,somewhatLongOperation1 和 somewhatLongOperation2 可以被并行执行。
   假设我们不想并行运行这两个函数,那是不是就按照字面顺序执行他们好了呢?答案是否定的,我们只在其他函数依赖于 s1 和 s2 时才需要执行这两个函数。我们甚至在 concatenate 调用之前都不必执行他们——可以把他们的求值延迟到 concatenate 函数内实际用到他们的位置。
   如果用一个带有条件分支的函数替换 concatenate 并且只用了两个参数中的一个,另一个参数就永远没有必要被求值。在 Haskell 语言中,不确保一切都(完全)按顺序执行,因为 Haskell 只在必要时才会对其求值。

7.高阶函数

   函数当参数,把传入的函数做一个封装,然后返回这个封装 函数,达到更高程度的抽象。

//命令式
var add = function(a,b){
    return a+b;
}
function math(func,array){
    return func(array[0],array[1]);
}
math(add,[1,2]);    //3
8.尾调用优化

  指函数内部的后一个动作是函数调用。该调用的返回值,直接返回给函数。。 函数调用自身,称为递归。如果尾调用自身,就称为尾递归。递归需要保存大 量的调用记录,很容易发生栈溢出错误,如果使用尾递归优化,将递归变为循 环,那么只需要保存一个调用记录,这样就不会发生栈溢出错误了。

//不是尾递归
function sum(n){
    if(n===1){
        return 1;
    }else{
        n+sum(n-1);
    }
}

其运算过程如下:

sum(5)
(5+sum(4))
(5+(4+sum(3)))
(5+(4+(3+sum(2))))
(5+(4+(3+2+sum(1))))
(5+(4+(3+(2+1))))
(5+(4+(3+3)))
(5+(4+6))
(5+10)
15

//细数尾递归
function sum(x,total){
    if(x === 1){
        return x+toal;
    }else{
        return sum(x-1,x+total);
    }
}

其运算过程如下:

sum(5,0)
sum(4,5)
sum(3,9)
sum(2,12)
sum(1,14)
15

  整个计算过程是线性的,调用一次sum(x, total)后,会进入下一个栈,相关的数据信息和 跟随进入,不再放在堆栈上保存。当计算完后的值之后,直接返回到上层的 sum(5,0)。这能有效的防止堆栈溢出。 在ECMAScript 6,我们将迎来尾递归优化,通过尾递归优化,javascript代码在解释成机器 码的时候,将会向while看起,也就是说,同时拥有数学表达能力和while的效能。

9.闭包

  闭包就是能够读取其他函数内部变量的函数

10.范畴与容器

  我们可以把”范畴”想象成是一个容器,里面包含两样东西。值 (value)、值的变形关系,也就是函数。
  范畴论使用函数,表达范畴之间的关系
  伴随着范畴论的发展,就发展出一整套函数的运算方法。这套方法 起初只用于数学运算,后来有人将它在计算机上实现了,就变成了今 天的”函数式编程"。
   本质上,函数式编程只是范畴论的运算方法,跟数理逻辑、微积分、 行列式是同一类东西,都是数学方法,只是碰巧它能用来写程序。为 什么函数式编程要求函数必须是纯的,不能有副作用?因为它是一种 数学运算,原始目的就是求值,不做其他事情,否则就无法满足函数 运算法则了。
  函数不仅可以用于同一个范畴之中值的转换,还可以用于将 一个范畴转成另一个范畴。这就涉及到了函子(Functor)。
  函子是函数式编程里面重要的数据类型,也是基本的运算 单位和功能单位。它首先是一种范畴,也就是说,是一个容 器,包含了值和变形关系。比较特殊的是,它的变形关系可 以依次作用于每一个值,将当前容器变形成另一个容器

当下函数式编程比较火热的库

RXJS*
cycleJS
lodashJS、lazy*
underscoreJS
ramdaJS*

资料:https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/

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

推荐阅读更多精彩内容