在他出色的演讲中,Damian Conway 展示了如何实现一个新的声明符,他把这个声明符称为 your
,它会把任何值的变化输出到容器中进行调试。整件事让我担心 Perl 5 可能会超越 Perl 6,导致更多的命名混乱,因为我们已经得到了。所以我又开始让我们领先一点。
我们还不能在 Perl 6 中轻易地实现声明符,但花哨的容器是没有问题的。我们需要的只是一个能进行类型检查的 Proxy。后者可以通过在构造函数中进行类型捕获来实现。
class Watched {
has Mu $.container is rw;
my $quote-start = '⟨';
my $quote-end = '⟩';
method new(::T, :$name = '<unnamed>') {
my $self = self.bless(:container(T));
Proxy.new(
FETCH => method () { $self.container },
STORE => method (T $new-value) {
temp $quote-start;
temp $quote-end;
if $*ERR.t {
$quote-start := "\e[7m";
$quote-end := "\e[0m";
}
note "Container $name changed from {$quote-start ~ $self.container.gist ~ $quote-end} to {$quote-start ~ $new-value ~ $quote-end}";
$self.container = $new-value
}
)
}
}
获取容器棒我们需要使用绑定。遗憾的是,如果没有适当的宏支持,就无法自动获得容器名称,因为 Proxy
不支持与 Scalar
相同的接口。另一方面,手动提供它可以提供更多的灵活性。
my $c := Watched.new(Int, :name<$c>);
dd $c; # Int
$c = 42; # STDERR: Container $c changed from (Int) to 42
dd $c; # 42
我希望已经证明了在 Perl 5 和 Perl 6 中,多一个层次的间接性也同样有效。
更新:如果我们输出到 STDERR,我们最好测试一下 $*ERR
是否是一个 tty。
by gfldex