下面是随手写了一个简单的列子,看上去比较分离而且绕的调用方式
#!/usr/bin/perl -w
sub foo {
my ($a, $b, $out) = @_;
if ($a > $b){
$out->($a, $b);
}
else {
$out->($b, $a);
}
}
sub output {
my ($a, $b) = @_;
print “$a > $b\n”;
}
foo(1, 3, \&output);
最终执行的函数是最后一行,调用过程大概就是函数名output作为参数传到foo里,然后if和else里根据判断来执行output这个函数,最后打印信息
表达式\&output生成了一个代码引用code reference,即一个表示该函数的标量,可以像别的标量一样在一个标量变量中保存代码引用,或者像别的标量一样作为一个参数传递,还可以使用这个引用执行它表示的函数,所以就出现了上面的累死下面的语句:
$code_reference->(arguments …);
就像C里传递一个地址,然后通过指针遍历结构体的步骤类似
这里foo里的代码引用参数就称为回调,因为他是由foo的主调者提供的函数,在foo需要帮助时回调他;而foo函数体里的参数$out也称为吊钩hook,因为他提供了一个地方以供额外的功能可以被容易地吊着
这种方法重点在于通过把函数的部分功能参数化成调用其他函数,而不是固定其行为,可以使函数更灵活,这增加的灵活性会在想要函数做些改变时带来好处,例如,执行一次自动的自我检查,不是用许多可选的自测代码把函数弄乱,而是把测试部分与主算法分离,在简洁明了的前提下,能在运行时通过传递不同的代码引用参数使用或者不使用自测代码