标签:是你 知识 状态 定义 命令 相加 col erro exception
主要参考的是《Java函数式编程》高清华译版本
函数式编程其实就是编写非故意副作用的程序。
函数简单的说就是从A(定义域)到B(值域)的一个映射过程。当然具体的函数还有各种限制,具体见链接。
所以函数式编程也应该是一个从入参到返回值的黑盒子。
并不是所有人在函数式编程的定义上达成了共识。一般来说,函数式编程是使用函数来编程的一种编程范式。但是这个定义并不能解释最重要的一点:函数式编程和其他编程范式的区别,以及究竟是什么让它(可能)成为编程的最佳方式。
函数式编程中没有赋值语句,因此变量一旦有了值就不会再改变。更通俗的讲,函数式编程没有副作用——除了结算结果,调用函数没有别的作用。这样消除了bug的一个主要来源,也使得执行顺序变得无关紧要。因为没有能够改变表达式值的副作用,可以在任何时候对它求值。由于能够在任何时候对表达式求职,所以可以用变量的值来自由替换表达式,反之亦然——即程序是“引用透明”的。
理解事物是什么而不是什么往往都很重要。
函数式编程有时候被认为是一系列可以补充或替代的其他编程范式的技术,例如
1. 如果b==0,返回a 2. 否则a自增,b自减 3. 用新的a和b重新计算
另一方面,函数式编程是由“是”什么的元素组成,而不是“做”什么。a和b的和并不是会“造”出一个结果。例如2与3的和,并不是会造出5,它就是5——每当你遇到2+3,就可以用5把它替换。
那在命令式编程里面可以这样替换吗?有时候可以,但是有时候不改变程序的结果就无法做到——即如果替换掉的表达式没有副作用,就可以替换。在命令式编程里面,明显a和b在求和的过程中自身发生了变化,这就是一种副作用,这种情况是无法替换的。
所有,命令式和函数编程的最大一个不同是,函数式编程没有副作用。这意味着:
这里的“没有副作用”是指没有可观测到的副作用。函数式程序是由接受参数并返回值的函数复合而成的,仅此而已,你不关心函数内部发生了什么。但是在实际上,程序是为完全不函数式的计算机而编写的。所有的计算机都基于相同的命令范式,所以函数就是如下黑盒:
这是一种理论上的,实际上函数不可能完全没有副作用。函数会在某个时刻返回一个值,而这个值可能是变化的,这就是一个副作用。也可能会造成内存耗尽的错误,或者堆栈溢出的错误,导致应用程序奔溃,正在某种意义上就是一个可观测到的副作用。
所以函数式编程其实就是编写非故意的副作用的程序——副作用是程序预期的一部分。非故意的副作用也应该越少越好。
前面提到了函数式编程是编写没有副作用的程序,那么如何实现呢?函数式编程并非编写没有可观测结果的程序。是关于编写除了返回值以外没有可观测结果的程序。但是如果这个就是程序的全部,那用途不大。实际上函数编程需要可观测的作用,例如把结果显示在屏幕上。换句话说与外界的交互不会发生在计算过程中,而是发生在计算完成后——将会推迟副作用并单独应用。
public static int add(int a,int b){ while(b>0){ a++; b--; } return a; }
这段代码是完全函数式。完全没有其他可观测的作用。虽然可能结果不正确(在溢出的情况下),但是与没有副作用并不矛盾。即使返回错误结果也是函数式的。
public static int div(int a,int b){ return a/b; }
这个代码就不是函数式的,虽然没有改变任何变量,但是b=0时会抛出异常——这就是一个副作用。但是下面的是函数式的。
public static int div(int a,int b){ return (int)(a/(float)b); }
即使b=0,也不会抛出异常。
无论抛异常是否有意为之还是无意的,终归是一个副作用。尽管在命令式编程里面副作用一般也是我们想要的。最简单的形式如下:
public static void add(int a,int b){ while(b>0){ a++; b--; } System.out.println(a); }
这个程序并不返回值,但是把结果打印到了控制台上,这就是期望的副作用。但是下面的代码不是函数式的。因为返回了值又有意加上了副作用——编写除了返回值没有意外可观测结果的程序。
public static int add(int a,int b){ log(String.format("Adding %s and %s",a,b)); while(b>0){ a++; b--; } log(String.format("Returning %s",a)); return a; }
函数式编程就是编写非有意副作用的程序,如果需要副作用尽可能的延迟副作用发生的时机。如果既有返回值又有副作用,这种程序就不是函数式。
没有副作用(并不会改变外界的什么)并不足以让程序编程函数式的,同样函数式编程也不能被外界所影响——函数式程序的输出只能取决于自己的参数,这就意味着函数式代码不能从控制台、文件等读取数据,既函数式代码是引用透明的(不被外界影响到的代码是引用透明的)。
引用透明代码的特点:
它不会由于外部设备(数据库、文件系统)不可用、太慢或坏掉而崩溃——但是你的程序会。
标签:是你 知识 状态 定义 命令 相加 col erro exception
原文地址:https://www.cnblogs.com/CDNfast/p/10122758.html