什么是函数式编程思维

 我来答
就烦条0o
2018-08-03 · 知道合伙人软件行家
就烦条0o
知道合伙人软件行家
采纳数:33315 获赞数:46490
从事多年系统运维,喜欢编写各种小程序和脚本。

向TA提问 私信TA
展开全部
回答都有跑题,show概念之嫌,题主问的是函数式思维,这个问题我一直在思考,毕竟是方法论,能力有限,只能从切身实践告诉你
1.表达式化

最初的时候,需要转变观念,去可变量,去循环,把命令式改成表达式,注意,这只是把你丢在荒山野岭让你感受一下,离开熟悉的环境,地球依然在转,但是有个
重点,那就是一切都是表达式; 为什么是表达式呢?这个问题就像为什么鱼在水里?
因为函数式建立在lambda演算之上而非图灵机,只不过两者被证明等价,所以你可以在你的机器上跑全是表达式的代码,就如有人证明天空适合鱼生存,所以
鱼可以在天上游
当你接受了鱼可以在天上游之后,就该上正餐了

1.5 数据与行为分离
这也是和面向对象不一致的地方,面向对象强调数据与行为绑定,但函数式不是,确切的说函数式 函数与数据等价,所以你才可以将函数当参数与返回值,你在设计时,切勿让数据自己长腿能跑,其次,行为必须消除副作用,不可以偷偷把数据改了,习惯第一条后,应该不会的

2.高阶逻辑

了函数式,就不要在想循环,赋值这些低阶逻辑了,而应该更高阶的思考问题,这比转化表达式更难,函数式又叫声明式,也就是你要做什么,只要说一下就行,而
非写个遍历,做个状态判断,用函数式你不需要考虑这些,你不知道函数式的列表是怎么遍历的,中间向两边?
从后往前?这也是为何函数式适合并发的原因之一,你想知道列表中大于3的数有多少,只要,list.count(_ > 3)
而不是写循环,你可以直接写你的业务,不要拘泥于细节,有点像sql, 你需要什么告诉电脑就行,你或许会问,count foreach filter
这些函数怎么来的? 因为有了他们你才不需要写循环,他们把你留在高阶逻辑中,这个问题的答案请看下面

3.组合子逻辑 或又叫 自底向上的设计

数式和OO是反的,面向对象是自顶向下的设计,函数式是自底向上的设计,也就是先定义最基本的操作,然后不断组合,不断堆积以满足你的所有需要,如sql
定义了select, from, where...这几个组合子,来满足你的查询需求,同理函数式语言会提供foreach,
map等组合子(操作)来满足你的需求,所以你必须自下而上的设计你的代码结构,并且满足你的需求,当你只用组合子写代码时,你会发现你写的全是高阶逻辑

果这些已有组合子满足不了你,你就得自己写,foreach不行,你就自己写递归,我告诉你,递归背后也是组合子,这里一些'大神'应该不知道,在图灵机
里,递归就是方法不断调用自己没什么好说的,但是在lambda演算中,匿名函数是没法调用自己的,所以递归是用Y组合子(又叫不动点组合子)把递归函数
自己求解出来再调用的,这才可以实现递归,并与图灵机的循环等价,有点跑题了,总之要想顺手的写函数式,最好用面向组合子的设计,注意,不是必须,组合子
演算和lambda演算可以相互转化,也就是,你完全可以写一堆杂乱的表达式,但没有组合子逻辑来得清爽,Haskell大规模使用monad这个特殊组
合子,始其变得统一整洁

好了,总结一下
函数式思维,其实就是组合子逻辑,用简单的几个函数组合来构建复杂逻辑,始终以高阶的角度去表达问题,而非依赖副作用。
知道这点,你用java也可以写函数式代码了

但是,这也只是本人积累得来的感悟,绝不敢大肆伸张这就是函数式,我也在不断研究中,如有问题,还望大神指正
CP3大炮
2017-09-16 · TA获得超过1093个赞
知道小有建树答主
回答量:313
采纳率:90%
帮助的人:249万
展开全部
按照百度百科,据说函数式编程是计算机把运算当做函数处理。我本人用过一年左右Haskell(一种函数式编程语言),感觉有这些特点:
1 支持lamda表达式运算(lamda表达式的特点是替代运算,比如λx.xx的含义是属于输入x,结果是xx,如果有一个表达式为(λx.xx)y,函数是(λx.xx),输入是y,则结果是yy。
2 写不了循环,都用递归弄。
3 没有办法直接改全局变量,你只能把修改全局变量的函数传进函数操作(如果你有n个全局变量在一个函数中使用,在haskell中你要穿长度为n的数据量,这使得代码冗余,不过也保障了线程安全)。
4 高阶函数让一切变得方便,你可以把函数当做参数传入高阶函数(比如fmap,map,zip,fold等等),然后把传入的函数应用到传入的数据结构里,有点像C的函数指针。比如map可以把(a->b,输入a类型数据返回b类型数据)类型函数作用于整个数据类型为a的数组,map函数吧a->b类型函数作用于a类型数组中的每一项,然后返回类型为b的结果集。

5 对泛型的支持友好,你可以同时在函数声明中定义a类型b类型,数据类型安全有保障。更有甚者,在另外一个函数式编程语言idris中,数据类型(比如int)可以当成数据使用(这是很多程序语言都没有的)。
6 就Haskell而言,数据类型定义很灵活,对于除法,你可以用haskell自带的maybe类型(比如maybe double)作为返回类型,如果是有效值a就返回(Just a),如果是除0,你可以让结果返回Nothing。
7 Haskell中有一类东西叫type class,和Java里面的抽象类或者接口很像。如果你有数据类型a,b实现了一种type class(叫他class)的所有函数, 你可以把class里面定义的抽象函数用于a,b。这是多态的支持。如果你学得足够高深,函数式编程里面的Monad,Arrows等type class将会是你的常用技巧。
8 惰性求值。你可以定义一个无限长自然数表。如果你直接打印它,电脑尽其所能从0,1,2开始输出到内存溢出或者系统自己停止为止。如果你用了take函数,你可以之选择取前面5个值。此时电脑只生成0到4的表,因为从5开始数据没有用了。这可以大幅提升运行速度。
我说的这些都是在去年一年对函数式编程学习的小总结。需要学习的话,你可以上Hoogle(这不是google,一个haskell的官方API网站)查你不会的函数。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式