函数式编程的概念

题外话,最近在学习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

总结

函数编程主要是以单元为格式的编程规范,以函数思维为核心,函数可以作为参数,结果,对象等等。。

上一篇:APKAnalyser —— Android 静态虚拟分析工具


下一篇:JavaScript异常处理和事件处理