Re: RFC 319 (v1) Transparently integrate Ctie
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
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
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