你真的理解函数式编程吗?
Posted 架构之心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的理解函数式编程吗?相关的知识,希望对你有一定的参考价值。
本文来自作者 李龙生 在 GitChat 上分享「你真的理解函数式编程吗?」,「阅读原文」查看交流实录
「文末高能」
编辑 | 克拉克
前言
现在机器学习、人工智能的发展趋势如火如萘,很多培训班也在引入大数据、机器学习的课程,受到众多IT从业者的追捧,有一种势必与传统模式一决高下,分享半壁江山之势。
如果人工智能走向企业、社会,它带来的经济效益以及影响是巨大的,我们每个人不管从事什么行业都有必要了解一下人工智能的发展趋势。
机器学习背后隐藏着什么不可告人的秘密,让我们来揭开层层面纱,一窥究竟。
在面向对象语言满天飞的现在,很多人认为,函数式编程是一种仅仅存在于某些偏门语言中。
然而,纵观现代主流语言都在引进函数式特性,不同语言可能引进的程度不同。
如,我们最熟悉的 jdk,jdk8 已经引入了函数式编程的一些特性,可见大公司在不断引进新技术,唯有跟着技术前沿发展,我们才能立足于不败之地。
本篇文章的目录结构如下:
为什么函数式编程会在这个时期流行起来?这种思想出现至少10年以上了,那一定是它自身的某些特性符合了这个时代的特性,解决了企业中设计、开发中遇到的各种问题,这是一个流程技术的内在驱动力,在函数式编程里面函数的地位很高。
如面向对象中的对象一样常见,有三个俗称三板斧的利器,map、filter、reduce,它将在以后我们的编程中随手不离,函数式编程为我们开启了另一个思考维度。
思想转化
计算机科学的进步经常是间歇式的发展,先形成好的思路、然后出来这种思路下面的语言,之后便会成为某一时代的主流。
例如第一种面向对象的语言 simula 1967 年发明,直到1983年的面向对象的 C++ 才流行起来,早年 java 总被认为太慢,编程迟钝,内存消耗太高不适合高性能的应用。
如今计算机硬件已经不再是制约条件,硬件的变迁把它变为了极具吸引力的语言,从国内大部分公司应用即可看出来。
那么大家想一下,如今硬件仍然在飞速发展,那么更高级的面向函数式编程、语言会不会更适应这个时代?
函数式思想
什么是函数式编程?
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。
个人理解就是我们的编程是以函数作为单元来处理各个业务逻辑,函数既可以当做参数传来传去,也可以作为返回值,可以把函数理解一个值到另一个值得映射关系。
由于函数式编程方式更适合于数据处理,随着存储器容量升高、计算机处理能力大幅提高,它的优势更加明显,最近支持函数式编程的语言也逐渐流行。
比如 python、scale 等都因它们对函数式编程的支持被人们重视,从被遗忘的角落重新拾起。
函数式编程因为其特点更适用于统计分析数据、科学计算、大数据处理等方面工作,当然并不限于这些,在web开发、服务器脚本等其它方面也很不错,而面向对象编程更适合于开发和处理业务性强、功能模块完备的大型业务系统。
优势特点
代码简洁、开发快速
函数式代码同命令式相比代码量要少很多,一行顶十行,所以实现一些功能也比较简洁,作为开发者的我们,还是对代码更亲切一些,来看一个具体例子,从中体会其特点。
功能描述:统计文本或网页中单词的频率TF(term frequency),词频在计算网页质量、信息检索中是一个重要概念,下面来看一下简化代码:
命令式实现
/** * Created by lilongsheng on 2017/11/5. */ public class Words { /** * 虚词过滤 */ private static Set<String> NON_WORDS = new HashSet<String>(){ {add("the");add("and");add("of");add("to");add("a"); add("i");add("it");add("in");add("or");add("is");add("d"); add("s");add("as");add("so");add("but");add("be");}}; /** * 命令式方式过滤实现 * @param words * @return */ public static Map wordFreq1(String words){ TreeMap<String,Integer> wordMap = new TreeMap<>(); Matcher m = Pattern.compile("\\w+").matcher(words); while (m.find()){ String word = m.group().toLowerCase(); if (! NON_WORDS.contains(word)){ if (wordMap.get(word) == null){ wordMap.put(word,1); }else { wordMap.put(word,wordMap.get(word)+1); } } } return wordMap; }
函数式实现
/** * 将待处理对象转为列表集合 * @param words * @param regex * @return */ private static List<String> regexToList(String words,String regex){ List wordList = new ArrayList<>(); Matcher m = Pattern.compile(regex).matcher(words); while (m.find()) wordList.add(m.group()); return wordList; } /** * 对集合统一处理 * @param words * @return */ public static Map wordFreq2(String words){ TreeMap<String,Integer> wordMap = new TreeMap<>(); regexToList(words,"\\w+").stream() .map(w -> w.toLowerCase()) .filter(w -> !NON_WORDS.contains(w)) .forEach(w -> wordMap.put(w,wordMap.getOrDefault(w,0)+1)); return wordMap; } public static void main(String[] args) { String test = "Before the popularity of network communicative tools, such as Weibo and WeChat, people get used to know a person by face and face talk, but now the situation has changed, the young generation tend to know a person by network social communicative tools. If they are interested in making friends, then they will be friends online first and then keep trace with the former information on the record. It seems that we can learn a person so fast and convenient. There is a short video about a girl dated a guy, but the guy did not have any account on the Internet, then the girl felt not comfortable and started to question if the guy was a criminal. The video satirizes people to rely on the Internet too much. They rather to communicate with a person by the Internet instead of face and face talk, while the latter is much trustworthy"; System.out.println(wordFreq1(test).toString()); System.out.println(wordFreq2(test).toString()); } }
函数式编程思维是对集合统一处理、统一操作,而命令式编程需要取出来每个单词单独处理,单独计数,而函数式只需要传入待处理对象集合、处理规则,我们不需要关注于具体细节,这样编程不仅仅减少了出现bug的概率而且提高了IT人员开发效率,何乐而不为呢。
易于理解,抽象度高
让我们再来看一个在开发中,我们经常遇到场景,例如我们有一个List
没有副作用,变量无状态
给定一个数集A,对A施加对应法则f,记作f(A),得到另一数集B,也就是B=f(A)。
那么这个关系式就叫函数关系式,简称函数。函数概念含有三个要素:定义域A、值域C和对应法则f。其中核心是对应法则f,它是函数关系的本质特征。
概念分析
闭包
一种特殊的函数,绑定了函数内部引用的所有变量,把它引用的东西都放在一个上下文中“包”了起来。
百科定义:包含两层含义要执行的代码块(自由变量以及自由变量引用的对象)和自由变量的作用域。
接收一个值返回另一个值,好了前提条件已经有了让我们来完成一个函数,计算两个数的相加操作,如下:
def plus(senior): return senior + 100 if __name__ == '__main__': result = plus(3) print result
def plus(senior): def pluaA(second): return senior + second return pluaA if __name__ == '__main__': pluaA = plus(3) result = pluaA(2) print result
高阶函数
匿名函数
def plus2(senior): return lambda second:senior+second if __name__ == '__main__': pluaA2 = plus2(3) result = pluaA2(2) print result
柯里化
语法糖
性能优化
缓求值
尾递归、尾调用
顾名思义,尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部 ,尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数和普通递归区别在于内存占用。
总结
近期热文
《》
《》
《》
《》
《》
《》
GitChat 与 CSDN 联合推出
《GitChat 达人课:AI 工程师职业指南》
「阅读原文」看交流实录,你想知道的都在这里
以上是关于你真的理解函数式编程吗?的主要内容,如果未能解决你的问题,请参考以下文章