闭包的好处

今天看了swift中的闭包一节, 看到最后值捕获时我才明白闭包的便利性. 如果没有值捕获, 那么支持闭包的特性跟C语言的函数指针比除了可以创建匿名函数与函数嵌套定义外恐怕没有什么优势. 但是有了值捕获这一功能闭包可以大大增加写代码的便利性.
下面是swift的一个闭包的例子:

func testclouser(t1 : Int) -> () -> Int {
var tst = 3;
func inc() -> Int {
tst += t1;
return tst;
}

return inc;
}

let fun = testclouser(9);
let fun2 = testclouser(3);

println(fun());
println(fun());

println(fun2());
println(fun2());

其输出结果如下:

12
21
6
9

可以看到从现像上看fun将tst, t1包了一份进入自己的闭包中作为全局变量, 但是这个全局变量并不能被其他函数或闭包访问, 而且fun与fun2虽然是由同一个函数体生成并且都包入了tst与t1变量, 但是fun与fun2算是两个独立的闭包, 所以fun与fun2都会有自己的全局tst, t1变量, 所以才会导致如上结果. 这种特性用C语言其实并没有太好的方法去模拟. 只能和类似的方法去实现.
下面是C语言的类似实现:

#include
#include

struct testclouser {
int tst;
int t1;
};

void testclouser_capture(struct testclouser *clouser, int t1)
{
assert(clouser);
clouser->tst = 3;
clouser->t1 = t1;
}

int testclouser_do(struct testclouser *clouser)
{
assert(clouser);
return clouser->tst += clouser->t1;
}

int main()
{
struct testclouser tc1;
struct testclouser tc2;

testclouser_capture(&tc1, 9);
testclouser_capture(&tc2, 3);

printf("%dn", testclouser_do(&tc1));
printf("%dn", testclouser_do(&tc1));
printf("%dn", testclouser_do(&tc2));
printf("%dn", testclouser_do(&tc2));

return 0;
}

这里只是对栈来模拟闭包, 可以类似这里的实现来对堆模拟闭包.

从代码上比较可以看出, 当我们需要实现类似上面的需求时, 虽然C可以实现, 但是会增加代码量而且看上去会很繁琐, 而在支持闭包的语言中, testclouser_capture的操作会被编译器做掉, 写出来的代码可以更简洁, 更清晰.



发表评论