> 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

Reply via email to