函数式编程笔记

濮俭
2023-12-01

参考来源:

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

http://www.cnblogs.com/huxi/archive/2011/06/18/2084316.html

函数式编程使用一系列函数解决问题。函数仅仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。任何情况下,使用相同的参数输入始终能产生同样的结果。输入数据“流过”一系列函数,每一个函数根据输入产生输出。

函数式风格避免编写有“边界效应”(side effects)的函数:修改内部状态,或者是其他无法反应的在输出上的变化,应避免这种风格。完全没有边界效应的函数称为“纯函数式(purely functional)”。意味着不使用在程序运行时可变的数据结构,输出只依赖于输入。

函数式风格有以下特点:

①逻辑可证:学术上优点,没有边界效应使得更容易在逻辑上更容易证明程序是正确的,而不是通过测试。

②模块化:一个函数只做一件事

③组件化:小的函数组合成新的功能

④易于调试:每一个函数都是检查数据是否正确的接口,更快速的排除没有问题的代码

⑤易于测试:不依赖系统状态的函数测试前无须构造测试桩,编写单元测试更简单

⑥更高的生产率:产生的代码比其他技术的少,更容易阅读和维护

函数式编程的一些特点(百科):

①闭包和高阶函数:闭包在接下来介绍,高阶函数:即可以使用函数作为输入变量的函数就为高阶函数

②惰性计算:表达式不是在绑定到变量时就求值,而是在求值程序需要产生值时进行计算,也叫延迟求值,相对应的叫热情计算或严格计算。

③递归:使用递归作为流程控制。

④引用透明:即如果提供同样的输入,那么函数总是返回同样的结果。

如何辨认函数式风格:

①函数是一等公民:函数作为参数传递或者是作为返回值

②匿名函数(lambda):lambda函数提供编写匿名函数的能力

③封装控制结构的内置模板函数:为避开边界效应,应避免使用变量,仅仅为了控制流程而定义的变量和流程中产生的临时变量是最需要避免的。

使用过滤得到正数:

lst_0 = [1, 2, 4, -4, -5]

lst_1 = list()

for i in range(len(lst_0)):

if lst_0[i]>0:

lst_1.append(lst[i])

这段代码展示了整个流程,实际上Python中有个过滤函数:

lst_1 = filter(lambda n: n>0, list)

④闭包(closure):闭包是绑定了外部作用域的变量(但不是全局变量)的函数。大部分情况下外部作用域指的是外部函数。闭包使得函数更加灵活,即使程序运行至离开外部函数,如果闭包课件,则被绑定的变量仍然有效;每次运行至外部函数,都会重新创建闭包,绑定的变量时不同的,不需要担心在旧闭包中绑定的变量会被新的覆盖。

Python2中,闭包无法修改绑定变量,Python3中加入关键字nonlocal来支持修改绑定变量。但不管如何,你总会访问到绑定变量。

⑤内置不可变的数据结构

⑥递归:递归是另一种取代循环的方法。递归很少被用到,如果一个递归无法被编译器或者解释器又换,很容易产生栈溢出;另一方面复杂的递归往往让人迷惑,不如循环清晰,众多最佳实践指出使用循环而不是递归。

闭包详解(javascript):javascript特点:①在函数内部可以直接读取全局变量②函数外部无法读取内部变量。

①e.g.:

var = 99;

function f1(){

alert(n);

}

fi(); //99

②e.g.

function f1(){

var n =99;

}

alert(n); //error

声明变量需要var关键字,要不然声明的就是全局变量。

闭包的代码:

function1(){

var n =999;

function2(){

  alter(n);

}

return f2;

}

var result=f1;

result(); // 99

其中f2函数就是一个闭包,闭包就是读取其他函数内部变量的函数。


                                                    


 类似资料: