Preparations for your
In his excellent speech Damian Conway showed how to implement a new declarator he called your
that will output any value change to the container for debugging. The whole thing made me worry that Perl 5 might overtake Perl 6 causing even more naming confusion as we got already. So I set out to get us ahead a little again.
We can’t easily implement declarators in Perl 6 yet but fancy containers are no problem. All we need is a Proxy that does a type check. The latter can be achived with a type capture in the constructor.
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 } ) } }
The get a container stick we need to use binding. Sadly without proper macro support there is no way to get hold of the container name automatically because Proxy
does not support the same interface as Scalar
. At the other hand providing it manuelly gives a little more flexibility.
my $c := Watched.new(Int, :name<$c>); dd $c; # Int $c = 42; # STDERR: Container $c changed from (Int) to 42 dd $c; # 42
I hope to have shown that one more level of indirection works equally well in Perl 5 and Perl 6.
UPDATE: If we output to STDERR we better test if $*ERR is a tty.
-
August 21, 2017 at 23:062017.34 Going ⚛ | Weekly changes in and around Perl 6