函数式编程主要体现在,1.避免数据可变 2.把函数作为值使用,它可以作为参数传递,作为值返回,可以赋值给其他变量
函数式语言在函数编程实现,也能在其他编程方式实现他
函数闭包,在解决如果这个变量不是局部变量,也不是参数,要怎么使用这个变量
高阶函数经常是多态的,但两只不是相互必然的关系
调用闭包函数分为两个部分,一部分是这段函数的代码,另一部分是他的作用域
词法作用域:根据函数定义的环境找到值
动态作用域:根据调用栈的环境找到值(e.g 捕获异常)
ref类型 ml的data可变类型
x的reference不会改变只会改变reference里面的值,这点跟js不同
在js,a的reference就被重新指向了,ml则是改变reference里面的内容
callback,利用闭包,当回调被调用时,内部数据不需要体现在函数类型里面,callback实现者也不需要考虑会有什么类型的内部书数据
抽象数据类型,通过定义一个函数集合来实现,在一个闭包函数里面,实现这个函数集合,这个私有变量不会被外界访问,每次返回新的S,S的xs拿到的是insert过后的xs
datatype set = S of { insert : int -> set, member : int -> bool, size : unit -> int }
val empty_set =
let
fun make_set xs = (* xs is a "private field" in result *)
let (* contains a "private method" in result *)
fun contains i = List.exists (fn j => i=j) xs
in
S { insert = fn i => if contains i
then make_set xs
else make_set (i::xs),
member = contains,
size = fn () => length xs
}
end
in
make_set []
end
fun use_sets () =
let val S s1 = empty_set
val S s2 = (#insert s1) 34
val S s3 = (#insert s2) 34
val S s4 = #insert s3 19
in
if (#member s4) 42
then 99
else if (#member s4) 19
then 17 + (#size s3) ()
else 0
end
没有闭包要怎么实现闭包:
- 在Java中,我们可以实现一个内部class,内部class的method拿到需要闭包的值,闭包的私有数据需要是final不可变类型
- 在C中,我们虽然可以传递函数,但是函数是不可以在函数内部定义,函数必须在定义在最前面,因为不存在非局部变量(不是参数和局部变量),那参数就需要逐层传递,不能利用内部嵌套函数,获得非局部变量,需要动态去传这个env值(上下文)
而对于有闭包的情况,ml可以不去传递这个env,这个值在它定义的时候已经被绑定
闭包好处在于,可以将map分离,map的制定者知道怎么去遍历递归数据,map的使用者知道怎么处理数据,而像C版本的实现当中,map的制定者就必须将env传递,而这个env对于制定者来说是不必要,但是没有这个env,使用者就无法去拿到这个数据,因为这个函数的调用是在制定者当中的