Let's pick up this old mail before it gets completely warnocked ;-)
For the record, this discussion only applies to scalar implementation
types. For example for Arrays I expect things to work by overriding the
method postcircumfix:<[ ]>.
Also I'm far from being an expert on this field, so feel free to correct me.
Kyle Hasselbacher wrote:
> My patchwork readings lead me to believe I could test Perl 6's
> tie-like feature with something like the below code, which I don't
> expect to even compile, what with '???' in places. My question is:
> am I on the right track? Obviously there are details I haven't nailed
> down, and any guidance would be appreciated.
I think the you're on the right track, but I'm not sure about some details.
For one it scares me to think that we do a full-blown multi dispatch on
every FETCH/STORE operation, which might become quite expensive.
> # Scalar is Any does Container does Order
>
> class ScalarTester is Scalar {
> has @.log;
>
> multi STORE ( Any $thing ) {
> @.log.push( STORE => $thing );
These non-operator routines should all be methods; 'multi' by itself
defaults to subs, not methods (iirc).
Also you'd have to quote STORE; otherwise it's interpreted as a named
argument, which Array.push doesn't know how to handle.
> nextsame;
> }
> multi FETCH() {
> @.log.push( 'FETCH' );
> nextsame;
> }
> multi TEMP() {
> @.log.push( 'TEMP' );
> nextsame;
> }
>
> multi infix:<=> ( ??? ) {
> @.log.push( 'infix:<=>' );
> nextsame;
> }
If we do FETCH/STORE, then the assignment will call the STORE method for
you, so there's no reason to override infix:<=>.
Also note that
my $x = 3;
foo($x);
does dispatch based on the type of the stored thing (Int), not on the
type of the Scalar container
> multi infix:<:=> ( ??? ) {
> @.log.push( 'infix:<:=>' );
> nextsame;
> }
Binding replaces the container; the container implementation shouldn't
see this. (Not sure though)
> multi infix:<::=> ( ??? ) {
> @.log.push( 'infix:<::=>' );
> nextsame;
> }
Same here.
> multi infix:<=:=> ( ??? ) {
> @.log.push( 'infix:<=:=>' );
> nextsame;
> }
I also don't expect =:= to be handled by the container; but rather as a
very general sub that compares memory addresses at some point.
> # since Scalar does Order, there are ~20 other methods to test.
> }
>
> my $t is ScalarTester;
> is $t.log, (), 'log is empty';
> lives_ok { $t = 'bughunt' }, 'can assign to test scalar';
> is $t.log, ( 'STORE' => 'bughunt' ), 'log reflects assignment';
> lives_ok { my $discard = $t }, 'can access test scalar';
> is $t.log, ( 'STORE' => 'bughunt', 'FETCH' ), 'log reflects access';
Cheers,
Moritz