函数式编程总结

函数式编程的概念

函数式编程理念来自于数学中的函数。函数的概念:对于两个变量x和y,如果每给定x的一个值,都有一个y值与之对应,那么我们就说y是x的函数。如下即是一些函数:


f(x)=5x^2+4x+3
g(x)=2f(x)+5=10x^2+8x+11
h(x)=f(x)+g(x)=15x^2+12x+14

这种只关心输入数据和输出数据的关系,即数学表达式里面说的mapping关系的编程模式叫做函数式编程。对于函数式编程来说,x是输入数据,y是输出数据。

函数式编程的特点:

stateless:函数不维护任何外部或者内部状态,也不依赖任何内部或者外部状态。只做一件事:你给我输入数据,然后我给你输出数据。

immutable:输入数据不变。输入数据变了,相当于函数之间就是有状态了(隐式地),调用顺序一变,整个结果就有可能变化。

函数式编程的优势:

没有状态就没有伤害:无状态的代码功能性

并行执行无伤害:因为无状态,线程安全,可并行执行

Copy-Paste 重构代码无伤害

函数的执行没有顺序上的问题

函数式编程的劣势:

数据拷贝比较严重。因为无状态,所以数据都是拷贝的。但是这并不代表性能会很差,因为无状态,所以多线程不需要加锁,性能反而可能更好。

函数式编程的思维方式:

函数式编程关注的是:describe what to do , rather than how to do it.于是, 我们把以前过程式的编程范式叫做Imperative Programming(指令式编程). 而把函数式编程编程范式叫做Declarative Programming(声明式编程)。 一个具体例子:

我们有 3 辆车比赛,简单起见,我们分别给这 3 辆车 70% 的概率让它们可以往前走一步,一共有 5 次机会,然后打出每一次这 3 辆车的前行状态。

指令式编程的写法(python):


from random import random
 
def move_cars():
    for i, _ in enumerate(car_positions):
        if random() > 0.3:
            car_positions[i] += 1
 
def draw_car(car_position):
    print '-' * car_position
 
def run_step_of_race():
    global time
    time -= 1
    move_cars()
 
def draw():
    print ''
    for car_position in car_positions:
        draw_car(car_position)
 
time = 5
car_positions = [1, 1, 1]
 
while time:
    run_step_of_race()
    draw()

上面的代码,从主循环开始,我们可以很清楚地看到程序的主干,因为我们把程序的逻辑分成了几个函数。这样一来,代码逻辑就会变成几个小碎片,于是我们读代码时要考虑的上下文就少了很多,阅读代码也会更容易。不像第一个示例,如果没有注释和说明,你还是需要花些时间理解一下。而将代码逻辑封装成了函数后,我们就相当于给每个相对独立的程序逻辑取了个名字,于是代码成了自解释的。但是,你会发现,封装成函数后,这些函数都会依赖于共享的变量来同步其状态。于是,在读代码的过程中,每当我们进入到函数里,读到访问了一个外部的变量时,我们马上要去查看这个变量的上下文,然后还要在大脑里推演这个变量的状态, 才能知道程序的真正逻辑。也就是说,这些函数必须知道其它函数是怎么修改它们之间的共享变量的,所以,这些函数是有状态的。

我们知道,有状态并不是一件很好的事情,无论是对代码重用,还是对代码的并行来说,都是有副作用的。因此,要想个方法把这些状态搞掉,于是出现了函数式编程的编程范式。下面,我们来看看函数式的方式应该怎么写?

函数式编程的写法:


from random import random
 
def move_cars(car_positions):
    return map(lambda x: x + 1 if random() > 0.3 else x,
               car_positions)
 
def output_car(car_position):
    return '-' * car_position
 
def run_step_of_race(state):
    return {'time': state['time'] - 1,
            'car_positions': move_cars(state['car_positions'])}
 
def draw(state):
    print ''
    print '\n'.join(map(output_car, state['car_positions']))
 
def race(state):
    draw(state)
    if state['time']:
        race(run_step_of_race(state))
 
race({'time': 5,
      'car_positions': [1, 1, 1]})

上面的代码依然把程序的逻辑分成了函数。不过这些函数都是函数式的,它们有三个特点:它们之间没有共享的变量;函数间通过参数和返回值来传递数据;在函数里没有临时变量。我们还可以看到,for 循环被递归取代了(见 race 函数)—— 递归是函数式编程中常用到的技术,正如前面所说的,递归的本质就是描述问题是什么

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一条叫做nemo的鱼

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值