函数式编程感悟是声明式编程,与命令式编程相对,其典型应用为SQL语句。为了清晰描述这个问题,我做了如下的场景比较:
我们知道SQL Server 由数据文件和检索引擎组成,当用户客户端需要检索一个学生,名字为tom时,怎将Sql语句“select id, name from student where name ='tom'”传递个检索引擎即可。我们修改table student, 增加一个age字段,这时我们检索age大于18的学生,则只需将sql语句“select id, name from student where age>18”传递给检索引擎即可。
假设我们的学生信息不是存放在SQL Server中,而是存在一个文本文件中,我们要手动开发一个学生信息检索引擎供客户端使用。
当用户客户端需要检索一个学生,我们在引擎中定义方法:
public List<Student>GetStudentByName(string name){
//...
}
然后客户端再调用;我们修改 student, 增加一个age字段,这时我们检索age大于18的学生,怎需要在引擎新加一个方法:
public List<Student>GetStudentGreaterAge(int age){
//...
}
比较两个事例,发现主要区别是,在引擎学生信息变化时,sql引擎没有变化,而我们写的学生信息检索引擎的变化了,增加了一个接口。从而说明在应对变化是函数式编程更有优势。
下面我们利用Lambda expression实现函数式编程引擎:
在引擎中定义如下方法:
public List<Student> GetStudents(Expression<Func<Student, Boolean>>){
//...
}
这样我们可以将查询条件通过lambda表达式传递,屏蔽了查询接口的变化。
在这里我强调的是接口变化,而不是实现变化。也许有人会问,给student增加一个字段age后,那么方法GetStudents(Expression<Func<Student, Boolean>>)是需要改变来从文本中获取age字段的,这是肯定的。但我们也可由在不改变此方法来实现这一变化,及通过一点的规则将age动态解析到GetStudents(Expression<Func<Student, Boolean>>)方法中。
总结:
- 函数式编程传递的是算法,命令是编程传递的是实体数据;
- 函数式编程特别适合分布式系统,因为算法的数据量很小,而实体数据的数据量很大(典型应用,MongoDB)