函数式编程概述

概述

函数式编程是一种编程模型

将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念。函数式编程的特点是,把控制权让渡给语言。
命令式编程天生的缺陷却使并行编程模型变得非常复杂,无论是信号量,还是锁的概念,都使程序员不堪其重。函数式编程就这样被推到了前线。状态不可变解决了并发编程中的最大问题

函数是函数式编程的第一型。

在面向对象编程中,我们把对象传来传去,那在函数式编程中,我们要做的是把函数传来传去,而这个,说成术语,我们把他叫做高阶函数。
在函数式编程中,函数是基本单位,是第一型,他几乎被用作一切,包括最简单的计算,甚至连变量都被计算所取代。在函数式编程中,变量只是一个名称,而不是一个存储单元,这是函数式编程与传统的命令式编程最典型的不同之处。

函数式编程关注做了什么,不关注怎么做

//把集合中的每个数字加一
list.map(x => (x+1))

做什么?每个元素加一
怎么做?不关心

特性

不可变性

不可变性指的是变量一旦确定,就不能再修改,这样做的好处是极大地方便了并发编程,变量的不变性,解决多线程/并发时锁的问题。大幅度提升多核处理器的性能。其次是降低了bug发生的概率。bug的发生经常出现在变量的位置。

惰性计算

惰性求值,有利于系统优化函数式程序的执行。将表达式复制给变量的时候不计算表达式的值,只在变量第一次被使用的时候才进行计算。惰性求值能大幅提高并行计算的性能。

  • 允许我们创建无线长度的序列
  • 减少存储空间
  • 产生更高效的代码
//演示惰性求值
list = [1,2/0,12]
print list.length
//输出是3。如果不是惰性求值会报错

闭包和高阶函数

柯里化

和命令式编程的对比

  • fp关注数据的映射,cp关心解决问题的步骤
  • fp注重读关系的描述,任何能在计算机中的东西之间的对应关系都可以描述
  • cp是一个指令序列,如何取数据,变量,控制,循环等。fp是一个表达式
  • 命令式编程是面向对象的,自顶向下。函数式编程是自底向上。通过不断地函数组合达到目的
    也就是先定义最基本的操作,然后不断组合,不断堆积以满足你的所有需要,如sql定义了select, from, where…这几个组合子,来满足你的查询需求,同理函数式语言会提供foreach, map等组合子(操作)来满足你的需求,所以你必须自下而上的设计你的代码结构,并且满足你的需求,当你只用组合子写代码时,你会发现你写的全是高阶逻辑
  • 程序的状态:
    • 命令式编程通过变量的变化表明状态、
    • 函数式编程通过函数创建新的函数或者返回值来保存程序的状态,每个函数的返回值,参数都带便了程序的状态

思维

  • 数据不可变
  • 一切皆表达式
  • 函数是第一公民
  • 递归替代循环
  • 高阶函数,lamba演算
  • 支持高并发

fp的本质

  • 高阶编程
  • 没有副作用
    • 函数的所有功能都是为了一个返回值,不做任何其他的事情。
    • 不修改变量的值
    • 使得fp的各部分的执行顺序可以随意打乱,有利于高并发。惰性求值,无需加锁

构造单元

Map

对集合中的每个元素进行映射,结果返回一个新的集合。

seq.map(s => fun(s))
seq.map(s => s+100)
seq.map(_+100)

Reduce

  • 用一个累积量来搜集集合元素。每次运算两个,运算的结果当作第一个,再从集合中选取下一个进行运算,直到集合为空。
  • 使用reduce时,需要规范化。直接使用reduce,方向是不被保证的。通过使用reduceLeft和reduceRight我们可以强制处理元素的方向。
  • 和reudce类似的是fold,对比如下:
reducefold
可以没有必须设定一个初始值
返回类型必须和列表的返回类型相同没有限制
seq.reduce(s,fun(s))
seq.reduceLeft(_+_)
seq.reduceLeft((x:Int,y:Int) => func(x,y))
seq.reduceRight((x:Int,y:Int) => func(x,y))

Filter

根据用户的定义将符合条件的值筛选出来,形成新的集合。
scala中提供了多种筛选方法。

seq.filter(s,fun(s))
seq.filter((x:Int) => 条件)
seq.filter((x:Int) => x>n)
// 选择第一个符合条件的
seq.find(_fun())
// 集合分片
seq.partion(条件)

递归迭代

迭代一定能转化成递归,递归不一定能转换成迭代。
递归中一定有迭代,迭代中不一定有递
递归是函数自身内部调用自己 ,问题的规模会越来越小。类似树形结构
- 有出入口
- 递推阶段:缩减规模,把问题分解
- 回归阶段:获得最简单的情况之后逐步返回
迭代是运算结果作为输入,问题规模基本不变。类似环形结构

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值