这篇文章从下面几个方面学习函数式编程:
1、数学公式和函数式编程有什么关系
举个简单例子吧,数学中有一个概念叫做映射(y=f(x)),说的通俗一点就是函数啦。而最熟悉的应该就是二次函数(抛物线y=a*x*x+b*x+c)
现在coding实现求抛物线上某一点的值,我们知道a,b,c是参数,x是自变量,y是因变量,如果是以前,我也许会这么实现(为了纪念我许久未写的c++,还是用c++来写一下)
double getParabola(double a,double b,double c,double x) { return a*x*x+b*x+c; }
问题一、给定抛物线,求x=2,x=3,x=4时的值,就是下面的做法了
resultA = getParabola(a,b,c,2) resultB = getParabola(a,b,c,2) resultC = getParabola(a,b,c,2)
这在程序中,是很正常的做法。但是,如果从数学的角度来看,有没有办法变得符合数学公式思维呢?以下是我的另外一种实现(这里用go来实现哈,因为c++我知道怎么写),
func getParabola(aa,bb,cc float32){ var a = aa var b = bb var c = cc a := func(x float32) { return a*x*x+b*x+c } return a }
然后,同样是对于问题一,解决方案如下
parabola := getParabola(a,b,c) resultA := parabola(2) resultB := parabola(3) resultC := parabola(4)
是不是跟求函数值一样?所以,数学关系在函数式编程中得到了很好的体现。
2、函数式编程有什么特点,go支持了哪些概念
函数式编程有三大特性
1、变量的不可变性: 变量一经赋值不可改变。如果需要改变,则必须复制出去,然后修改。 go中,string变量一经赋值,不可以像c++那样,c[2]='a'这样的修改,而是要显式转化为[]byte,然后进行修改。但是已经是另外一块内存了。
2、函数式一等公民: 函数也是变量,可以作为参数,返回值等在程序中进行传递。 这个特性,c++和go应该都是支持的。
3、尾递归:递归的概念在斐波那契数列的时候,就学习过了。如果递归很深的话,堆栈可能会爆掉,并导致性能大幅度下降。而尾递归优化技术,编译器如果支持的话,可以在每次递归时重用stack(尾递归表示递归调用发生在最后一步,这个时候,之前的结果都作为参数传递给最后一步的调用,所以之前的状态就没有任何作用了,所以可以重用stack)。
函数式编程常用技术
1、map&reduce&filter
map用于对每一个输入,调用同一个函数,产生一个输出,比如c++中的for_each,hadoop里面的map,python的map等。
reduce用于对每一个输入,加上上一个输出,得到下一个输出,比如python和hadoop中的reduce,
filter用于做过滤,比如c++的count_if等。
2、递归
3、pipeline
把函数实例放到一个数组或是列表中,然后把数据传给这个action list,输入顺序地被各个函数所操作(意思是每一个函数的输出,作为另外一个函数的输入,数据是流动的,计算是固定的,类似storm的概念),最终得到我们想要的结果。
4、其他(有待进一步学习)
3、函数式编程与运行效率
函数式编程最重要的一个概念就是函数式一等公民,函数跟变量是一样的。可以作为参数,返回值等。不赞成使用赋值语句,所以比较多的使用递归,所以函数式编程效率肯定会比较低。
最近我用的比较多的是闭包,闭包的概念就是一个环境(一个或多个变量)加上一个函数,每一次对闭包表达式求值,都得到一个隔离的结果,这跟普通函数是不一样的,普通函数就是一段可执行的代码,只要入口确定了,调用的位置也就确定了。举个例子,上面抛物线的例子,调用
a:=getParabola(0.2,0.1,0.3) b:=getParabola(0.1,0.1,0.4)
得到的是两条抛物线。之所以我觉得效率会降低,是因为闭包本身就是一个求值赋值的过程,涉及到变量的创建销毁。当然,我没有实际去测试性能。如果后续发行server效率降低,也许这是一个需要考虑的地方。
以上就是从go语言闭包谈函数式编程的详细内容,更多请关注亿速云其它相关文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。