> I'm kind of curious to know what you think would happen with the
> following. I've commented where I'm confident...
>
> interface Number;
> sub TIESCALAR;
> sub STORE;
> sub FETCH;
>
> package integer implements Number; # I really like this notation
Tangentially, yes, it is nice to read, but it prevents multiple
interface specifications. "use interface" is more consistent.
> sub TIESCALAR {...};
> sub STORE {...};
> sub FETCH {...};
>
> my Number $i; # Number is an interface, so just an assertion
> my integer $n; # integer->TIESCALAR($n);
> my non_tied $object;# Just an assertion
> defined($n); # Should be false
Yes. The only potential gotcha is if the user decides to do something
Really Evil and stores a value as part of their TIESCALAR method. Then
$n->FETCH will return that value and defined($n) will be true.
However, this is not the purpose of tie, and I think an appropriate
response is: Don't Do That. I agree with both you and Damian that TIE*
should be called on declaration for consistency. If a person doesn't
know how to use tie, well, that's not our problem. ;-)
> $n = 5;
> $i = $n;
> $n = 10;
> print $i;
> $i = $object; # Assertion fails
Assuming you've set up your C<use optimize> restrictions appropriately,
then yes. The key is really what 'non_tied' is setup as. If this is a
builtin type that optimizes itself to be a string object, then yes it
will fail. However, if 'non_tied' is just a synonym for 'float' (for
some odd reason) then the last line will be ok.
> > my int @b :64bit; # again, just an assertion
>
> Asserting what? That's not valid syntax at the moment.
But it will be. :-) See RFC 279.
> > @c = @b; # empty list passed still
> > @b = (1,2); # int->TIEARRAY(@a, '64bit'); @b->CLEAR(...);
>
> Hmm... I think this is somewhat ugly. Assuming that you want
> C<my int @b> to imply C<UNIVERSAL::isa(all(@a), 'int')> then tying the
> entire array seems a bit weird.
Not necessarily. The key is: *how* would you implement the assertion
check?
If you use tie, then your int class STORE method can do something like
this:
package int;
use base 'var';
# take defaults from var class
STORE {
if ( self->isa($_[1]) ) {
SUPER->STORE($_[0], $_[1]); # internally store
} else {
die "Bad data $_[1]" if ( $under_strict_types );
}
}
Now, there's a difference between _could_ do this and _must_ do this.
The idea here is that you could do this, and users wouldn't see any
difference between your custom types and builtin types.
> Er... You seem to be implying here that *all* classes should have TIE
> methods. Which is not good.
No, I wasn't trying to imply that, I'll clarify this point. TIE methods
are still completely optional.
> Err... Specifying which classes implement an interface in the
> interface specification is Wrong Wrong Wrong.
Yes, you're right, and it's way outside of this scope of this RFC,
actually. Your idea:
> my Pet $spot : isa(any(qw/Dog Cat/)) = new Camel; # oops!
is much better for this application.
> Can I just point out that nobody has yet proposed that you can attach
> attributes to a package?
Didn't Damian propose C<package Foo : interface> already? ;-)
> I'm not entirely sure what you're driving at here. I thought you were
> arguing that *all* packages that created objects would use tie magic,
> in which case the new attribute becomes unnecessary. And if you're not
> proposing that then :tie is too general in the cases where the module
> can only tie to specific variable types. I think you get better
> granularity with interfaces, which are way more general than a special
> new attribute.
No, let me back up a little. The idea is to make it so that tied
interfaces - which are really different beasts from OO interfaces
altogether because of their purpose - should be more closely integrated
into Perl 6. This would allow you to create custom, optimized,
strongly-typed variables that would function just like builtins:
my Matrix @a = ([1,2,3], [4,5,6]);
my NISMap %map :passwd = read_passwd_file();
my Apache::Session %session :transaction;
However, this is not to overshadow OO interfaces, which are needed for
functional methods, as you note.
The :tie attribute is a poorly chosen name. The original name was
:implicit, and was going to be attached to the TIE subs:
package Demo;
sub TIESCALAR : implicit { ... }
sub TIEHASH : implicit { ... }
sub TIEARRAY { ... }
So in this example, a user can say:
my Demo $x;
my Demo %x;
my Demo @x; # TIEARRAY not called
However, after thinking about this, I decided this was not a worthwhile
distinction. How often would you want this behavior? So I decided to
attach the attribute to the package:
package Demo : implicit;
But that really didn't connote what was going on. So I changed it to:
package Demo : autotie;
But then decided the 'auto' was redundant. However, the more I think
about it it appears that :autotie is perhaps the best name *if* we're
going to have an attribute.
However, I don't see why somebody would not want to be able to
automatically tie something, or why this would be seen as bad. And
that's why I mentioned that an attribute name was probably unnecessary.
Make sense?
-Nate