23 May 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.

Continuation

接着上一篇 sub Perl6 (*@Examples[5] is copy) 来接着讲 sub.

multi sub

如果你需要一个子程序对于传递进来参数类型的不同而区别对待的话,用 multi sub 是个很简单的方法。
比如定义一个 add 子程序,如果传递进来的是字符串将他们合并起来,数字的话则加起来;如果都不是的话中间用 - 连起来。
multi sub add (Num $a, Num $b) { return $a + $b; }
multi sub add (Str $a, Str $b) { return $a ~ $b; }
multi sub add ($a, $b) { return $a ~ '-' ~ $b; }

say add(1, 2); # 3
say add('a', 'b'); # ab
say add(0, 'a'); # 0-a
非常的方便。我想 multi 运用的比较多的是重载 op/操作符。这个下次讲。multi 还能操作方法:multi method

assuming

如果你要重复调用很多次子程序,而调用中子程序的某参数都是一样的。你可以使用 assuming(假设某参数):
sub multiply ($multiplicand, $multiplier) {
    return $multiplicand * $multiplier;
}
my $six_times = &multiply.assuming(multiplier => 6);

say $six_times(9); # 54
say $six_times(7); # 42

my $seven_times = &multiply.assuming(multiplier => 7);

say $seven_times(9); # 63
每一个子程序都有 assuming 这方法,我们管这种叫做 Curried Subroutines。

wrapping

有些时候你想在一个已定义的子程序里加些东西进去。可你又不方便改源代码(那子程序在一个模块里),而且你想实现原来子程序的功能(Perl 5 中可以试试 NEXT 模块),拷贝源代码是不方便的做法。
这样的例子在 log 时是非常常见的。在 Perl 6 中可以用 wrap 来实现这功能:
sub someaction (*@a) {
    say @a;
}

my $id = &someaction.wrap( {
    say 'start someaction'; # log start
    call;
    say 'end someaction'; # log end
} );

&someaction(1,2);
这样我们就非常简单的加进去了 log 功能。
这里的 call 是调用原子程序。
而如果你不想要这功能的时候,可以使用 unwrap 来去掉。
&someaction.unwrap($id);
当然,如果你是临时想重新定义改子程序的话,可以使用 temp (不仅对子程序,对变量也是有用的。)
{
   temp &someaction.wrap( {...} );
   # ...
}
wrap 可以多重嵌套

To be continued

See u next time.


blog comments powered by Disqus