Re: RFC 319 (v1) Transparently integrate Ctie

2000-09-27 Thread Piers Cawley

Nathan Wiger [EMAIL PROTECTED] writes:

  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.

It does?

   package integer implements qw/Number Countable/;

Et viola.

 
  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 Cuse 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.

I think you're missing the point. What does 'print $i' print? What
happens if you do C$n = $i? Does $i 'remember' that the number that
got assigned to it is an integer? What is the mechanism for that? It
seems that there will need to be some pretty far reaching changes to
Perl if you want this to do the Right Thing. Assuming we know what the
Right Thing is.

 
  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.

Ah. I'll marshall arguments there then.

  
  @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
  Cmy int @b to imply CUNIVERSAL::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 );
   }
}

Having the programmer implement this assertion check (or not) is a
Very Bad Idea. Assuming we're expecting to get some compiler
optimization from this then things should be enforced rather more
robustly.

  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. 

Okay. It's just that your example that I quoted and you cut out seems
to imply otherwise.

  Err... Specifying which classes implement an interface in the
  interface specification is Wrong Wrong Wrong.
 
 Yes, you're right,

Phew.

  Can I just point out that nobody has yet proposed that you can attach
  attributes to a package?
 
 Didn't Damian propose Cpackage Foo : interface already? ;-)

Not in an RFC, no.

  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:
 

Re: RFC 319 (v1) Transparently integrate Ctie

2000-09-26 Thread Piers Cawley

Perl6 RFC Librarian [EMAIL PROTECTED] writes:

 This and other RFCs are available on the web at
   http://dev.perl.org/rfc/
 
 =head1 TITLE
 
 Transparently integrate Ctie

On the whole I think I'm liking this. But it needs work.

my packed $a;   # just an assertion, RFC 218
$a = get_binary;# packed-TIESCALAR($a); $a-STORE(..);

I'm not sure there's any reason to delay the tie; It kind of depends
on what happens to stuff like 'defined($a)'. RFC 218 was brought
forward because I didn't want magic to be happening in cases where
Cmy Foo $bar was using a Foo that was a superclass, and there was no
mechanism for knowing that at the time. 

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
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

$n = 5;
$i = $n;
$n = 10;
print $i;   
$i = $object;   # Assertion fails

$a = more_data; # $a-STORE(...);
$a++;   # $a-STORE($a-PLUS(1));
undef $a;   # $a-DESTROY;
 
my int @b :64bit;   # again, just an assertion

Asserting what? That's not valid syntax at the moment.

@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
Cmy int @b to imply CUNIVERSAL::isa(all(@a), 'int') then tying the
entire array seems a bit weird.

 Note that the CTIE* methods will only be called if they exist, just
 like currently. If a given CTIE* method does not exist, then the
 appropriate error should be spit out:
 
my Pet @spot = ("fluffy");
Can't locate method "TIEARRAY" via package "Pet"
 
 In this case, the package CPet has declared that it can't handle
 arrays, which is just fine.

Er... You seem to be implying here that *all* classes should have TIE
methods. Which is not good. It's especially not good in cases where
the class is actually an interface. Hmm... maybe we should have the tie
behaviour only happen if the package is declared as implementing an
appropriate 'Tie::Foo' interface:

package integer implements Tie::Scalar;

Note that this would imply that the Tie::Foo modules in the standard
library become interfaces, but I'm not sure that that would be any
great loss...

 =head2 Optimization and Inheritance
 
 One of the main goals behind doing something like this is being able to
 create custom variable types that can take advantage of optimizations,
 and having these variables walk and talk like builtins.
 
 For this reason, it is further proposed that all variable types be
 handled through basic method inheritance in Perl 6. Essentially,
 everything becomes an object and is fully overrideable and redefineable.
 So, for example:

Whoa, now you're stretching.

 [...]

 =head2 Type checking
 
 Nat's upcoming RFC on type checking will propose a Cuse strict 'types'
 pragma. Type checking would be trivial to implement by combining aspects
 of this RFC with the Cuse optimize concept:
 
package Pet : interface;   # RFC 265
use optimize types = ['Dog', 'Cat'];
 
 With this declaration, Perl is now told that anything of type CPet can
 be either a CDog or a CCat. 

Err... Specifying which classes implement an interface in the
interface specification is Wrong Wrong Wrong.

 This means that in your main code:
 
use strict 'types';
my Pet $spot = new Camel;   # oops!
 
 The second line would raise a syntax error.

If your client code wants to insist that the only pets it's interested
in are Dogs or Cats then you should make that assertion somewhere.
You certainly shouldn't assert it in the interface declaration.
Check out the 

my Pet $spot : isa(any(qw/Dog Cat/)) = new Camel; # oops!

style that I proposed elsewhere.

 =head2 The C:tie attribute
 
 Making Ctie this seamless may scare some people. In this case, we may
 wish to add an C:tie attribute that can be specified on the
 Cpackage:
 
package Pet : tie; # will be auto-tied

Can I just point out that nobody has yet proposed that you can attach
attributes to a package?

 
 Placing this on the package, and not individual subs, makes more sense
 because it dictates how all the package's methods interact.
 
 The idea here is that by fully integrating these concepts, a separate
 Ctie function will no longer be necessary and will instead be replaced
 by a simple C:tie package attribute (or no attribute at all).

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 

Re: RFC 319 (v1) Transparently integrate Ctie

2000-09-26 Thread Nathan Wiger

 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 Cuse 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
 Cmy int @b to imply CUNIVERSAL::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 Cpackage 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