题外话,最近在学习scala和jdk8的时候接触到了函数式编程这一概念,于是学习了下当做笔记。
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。(摘自百度百科)
上面的太饶,简单来说函数式编程就是一种编程方式或者说思想,以函数为单元来处理业务逻辑,也可作为返回值,不依赖不改变外界状态。
函数为一等公民,以函数为单元完成各种操作,函数是自变量到因变量的一一映射,即一个值到另一个值的映射,结果可作为参数,套来套去的。。它可以将计算描述为表达式求值并避免了状态和数据改变。
使用函数式编程的优缺点
优点:
1.简便,支持闭包和高阶函数,大量使用函数减少重复的代码,简化编程
2.方便代码管理,函数式编程不依赖、也不改变外接状态,只要输入参数返回结果必然相同,这样每个函数作为独立单元更有利于单元测试和除错,以及模块化组合,方便管理。
3.易于并发,因为它不改变变量,无需考虑线程,死锁的问题。
缺点:
1.数据一直不可改变可能长期占用耗费cpu存储资源。
2.经常为了提速度不提供自动边界检查或垃圾回收机制等功能
几个概念
柯里化
在一个函数中首先填充几个参数(然后再返回一个新函数)的技术称为柯里化(Currying),简单来说就是将函数的参数变为一个参数的格式,函数可作为参数。
语法糖
程序可阅读性高,简洁方便的写法,对功能没影响但能更好的实现的语法为语法糖。
纯函数和非纯函数
这里有个纯函数的概念 ,纯函数是给定参数总是返回相同结果,函数的结果不依赖任何隐藏信息或程序执行改变的状态,也不依赖来自I/0装置的任何外部输入,无副作用。
举个栗子,在js中假定数组 var arr = [1,2,3,4,5];
arr.slice(0,2);//执行多少次返回的结果不会变 为纯函数
arr.splice(0,2);//执行两次就改变了返回结果 不纯的函数
非纯的其它例子
java的random() 【内部的随机数可能导致结果可能不一致】
java的printf() 【促使输出到I/O装置,产生副作用】
不变性
不变是指对象创建以后就不再发生变化,比如java.lang.String就是不可变的典型,假如创建了一个String实例,它不会发生变化,就算使用replace对象进行字符串替换,实际上也不会改变原有对象而是函数返回一个新的String对象作为给定字符串替换后的返回值。不变的对象在函数式编程中大量使用。
函数式编程(FP)和命令式编程
函数式编程关心数据的映射,命令式编程关心解决问题的步骤
这里的映射就是数学上“函数”的概念——一种东西和另一种东西之间的对应关系。
它的抽象程度可以很高,这就意味着函数式的代码可以更方便的复用。代码可以简洁。
举个栗子
public class Test1 {
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) {
//初始化list数据
List<User> userList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Test1 t = new Test1();
User user = t.new User();//实例化内部类
user.setName("linjw" + i);
userList.add(user);
}
//将list中的name 迁到新的list中
//命令行方式实现 侧重于怎么做 单独对user操作
List<String> newUserList1 = new ArrayList<>();
for (int i = 0; i < userList.size(); i++) {
newUserList1.add(userList.get(i).getName());
}
//函数式实现 不对单个user做操作 侧重于做什么,要完成什么 允许我们表达想要完成什么而不是怎样做,这也是循环的一个缺点,这样可以不用写循环
//jdk8 新特性 lambda表达式
List<String> newUserList2 = userList.stream()
.map(p -> p.getName())
.collect(Collectors.toList());
if(newUserList1.equals(newUserList2)) {
//输出=
System.out.println("=");
}
}
}
函数式编程和面向对象编程(OOP)
面向对象
java是典型的oop语言(从8开始引入基于对象的函数式),面向对象编程思想侧重于对象,传统的面向过程的编程难以解决重用,维护和扩展开的问题,逻辑复杂难懂。
如果说 程序 = 算法+数据结构 那么面向对象的程序 = 基于对象操作的算法+已对象为基础单位的数据结构
它主要是讲构成问题的各个事物分解为对象,
它的三大特性为:继承,封装,多态
面向对象也是基于过程去完成一件事,但是它更侧重于对象和对象可以做什么事。
举个简单的例子,做我喜欢吃的可乐鸡翅
使用面向过程的话大致过程为 我去菜市场买菜 -> 买可乐鸡翅所需的配料 -> 用锅煮
但是如果用面向对象的思维,假设用java实现,
public class OOP {
class Person {
public void maicai() {
System.out.println("人可以买菜,可乐鸡翅配料");
}
public void zuocai() {
//人可以使用锅做菜 先实例化锅
Guo guo = new Guo();
guo.zuocai();
}
}
class Guo {
public void zuocai() {
System.out.println("锅可以做菜");
}
}
public static void main(String[] args) {
OOP oop = new OOP();
Person p = oop.new Person();
p.maicai();
p.zuocai();
}
}
更多的可参考 https://yuedu.baidu.com/ebook/f7c46708a26925c52cc5bff4?pn=1&pa=1
总结
函数编程主要是以单元为格式的编程规范,以函数思维为核心,函数可以作为参数,结果,对象等等。。