去年在 p5-mop-redux 项目里看到他们在 Perl5 里实现了 Perl6 的面向对象设计的很多想法,尤其下面这段示例让人印象深刻:
use mop;
class Point {
has $!x is ro = 0;
has $!y is ro = 0;
method clear {
($!x, $!y) = (0, 0);
}
}
class Point3D extends Point {
has $!z is ro = 0;
method clear {
$self->next::method;
$!z = 0;
}
}
my $p = Point3D->new(x => 4, y => 2, z => 8);
printf("x: %d, y: %d, z: %d\n", $p->x, $p->y, $p->z);
这种 $!x
的变量是怎么实现的?最近几天,又在 CPAN 上看到另一个模块叫 Perl6::Attributes,实现了类似的语法。于是点进去一看,实现原来如此简单!
package Perl6::Attributes;
use 5.006001;
use strict;
no warnings;
our $VERSION = '0.04';
use Filter::Simple sub {
s/([\$@%&])\.(\w+)/
$1 eq '$' ? "\$self->{'$2'}" : "$1\{\$self->{'$2'}\}"/ge;
s[\./(\w+)][\$self->$1]g;
};
原来这里用到了 Perl5.7.1 以后提供的一个新特性,叫做 Source Filters 。在解释器把 file 变成 parser 的时候加一层 filter。