我所理解的函数式编程思维

  在理解函数式编程思维之前,应该先理解函数式编程的鼻祖 lamda演算。

  lamda的演算是丘奇在20 世纪三十年代引入的当时是为了解决判定行问题,即:是否所有的算法都有解?

  在解决这个问题的过程中,图灵和丘奇分别从两个不同角度来回答这个问题:

  图灵通过模拟人类解题的步骤,创造出了图灵机,然后利用机器的无限解题能力来得出答案,而丘奇则是另辟蹊径,丘奇定义了算法,然后丘奇创造了一个王国,这个王国里面只有一个元素,就是算法,而丘奇在这个王国里面也引入了数学,数学中的数字和运算符 丘奇全部使用算法重新定义了一遍(当然不是随便定义的,丘奇因为明白数学最本质的原理,所以才可以自己创造数学),现在数字有了,运算符有了,自然可以回答 是否所有的算法都有解的问题。

  这里只简单说一下,lamda演算中对于0的定义,在学习lamda演算之前,我对于0的认识就是无,nothing, 在lamda演算中对于0的定义是 不施加任何作用力,保持原样,1的定义是是加一次作用力,2的定义是施加两次作用力,我不知道我的理解是否正确,在lamda演算中 元素的最小单位是算法,数据是待处理的部分,那0的定义 就是在这个只有算法的世界中 没有算法,只有做到了没有算法 才符合0这个 无的定义,而没有算法的算法 就是输入数据,返回的还是原数据。

 

  上面只是简单的写了图灵和丘奇的示例,因为自己对于这些掌握的只是皮毛而已,但是丘奇的lamda演算中 最终的一个部分就是使用lamda项来重新定义数学,这个做法确实使人茅塞顿开,因为如果一切的都是算法的话,一个物质从一个状态到达另外一个状态,只不过是 经过无数个算法的转化而已,他和图灵有着本质的区别,图灵机的思维与人类的思维比较类似,因为图灵机时首先需要编写程序的,人类会把每一个解题步骤都写好,然后输入参数,返回结果,而lamda则抛弃了这种解决方式,而是直接从最本质的地方做起:一切状态的转换不过是算法的运算。

  那函数式编程思维与lamad演算在哪个地方比较像呢?我认为正式因为lamda抛弃了 步骤定义这个行为,使得 我们在进行任何的业务逻辑的编写的时候,都没有必要新写一个业务处理函数,而是使用已经存在的函数做简单的组合,即可得到结果,这样做的好处是代码大大的复用。举个例子:

  第一天:我们遇到一个需求,把所有的老师的名字中包含 于 的老师的名字 全部加上备注两个字

  普通思维就是:

  

addNameMark(teaList) {

  for (let i = 0; i < teaList.length; i++) {

    if (teaList[i].indexOf('于') > -1) {
        teaList[i] =teaList[i] + '备注';
    }

  }  

}

  函数式思维就是:

addNameMark(teaList) {

    teaList.map((item) => {
        item = item.indexOf('于') > -1 ? (item + '备注') : item;
    })

}

 

  这里面的差异是什么呢?对比两段代码,函数式思维 将 该处理逻辑,分为两个算法,第一个是处理循环的算法,第二个是处理 添加备注的算法,而普通思维则是没有算法的概念,只是单纯的完成任务而已,试想一下,随着需求不断迭代,后面只要需要用到循环的地方,我们都可以使用map,map于for循环相比,代码量减少了,同时语义化了,现在只是一个需求看不出来,但是入股是成千上万行代码 那节省的代码量是否客观呢?第二:通过将一段处理逻辑,给抽象成无数个算法的组装,这样做的好处是,被拆成独立的算法在未来可以得到复用,而普通思维编写的代码很难得到复用。

 

  所以函数式编程的核心是什么呢?即 函数式编程的世界原子就是函数,不存在比他还小的东西了,我们必须运用我们的抽象思维 将一段处理程序 给抽象成多个算法的组合,然后最终的结果不是普通解题的那种写法,而是数据像在管道里面行走一样 顺序穿梭于多个函数,最终得到最终的结果,这里的关键是 如果将一段业务代码给抽象成 多个算法的拼装?这里有一个建议,就是 一个算法只处理一件事情,如果你发现你的某些算法里面处理了两个事情,那就应当试着拆分了,然后对于如何定义一件事情还是两件事情,不同人的理解不一样,这里有一个方法就是:动词,寻找你的算法里面的东西,排除用于逻辑判断的动词后,如果出现了多个动词,则是处理了多个事情。

上一篇:JAVA8 Lamda函数


下一篇:JS学习二(循环)