Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On Sat, Sep 02, 2000 at 12:16:48AM -0400, John Tobey wrote: I agree with Michael that SETUP should be BLESS. You argue that it Oops, I mean Nate. Sorry, Michael! -John
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
Michael G Schwern wrote: Derived classes will never have to override a base's implementation, and all member variables should be private, and everyone will always use an accessor, and the UN will bring about world peace, and as long as I'm wishing for a perfect world, I'd like a pony. ;) I'm still not totally convinced that its so horrid to make the File::LockAndKey DESTROY call $self-SUPER::DESTROY manually... but it does break encapsulation. I'm inclined to agree here. I thought about this overnight, and I'm nervous about it again. It doesn't seem that it's that hard to add a single line to your SETUP or BLESS or whatever method that calls SUPER::SETUP. Remember, for all other methods you'd still have to do this manually. If you wanted to modify ADD or STORE, for example, just tweaking a few things, you'd have to manually call SUPER::STORE. I'm not convinced that this proposal saves enough typing to justify the problems that Michael mentions. Plus, what if you want to call a SUPER::'s DESTROY *not* at the start or end? sub DESTROY { my $self = self; # :-) # do a bunch of stuff here $self-SUPER::DESTROY(@_); # do a bunch more stuff here } It seems like this RFC enforces stuff that makes subclassing unnecessarily hard in some cases. At the very least, there should be a way to turn this off: sub SETUP : nocascade { } But then, if you're going to turn it off, why not just leave as-is and have the person turn it on manually by calling SUPER::? Your other RFC proposes calling NEXT:: manually, so the same philosophy I think should apply here. You could still have hooks for BLESS and REBLESS in bless(), but just make people manuallly call SUPER::BLESS and SUPER::REBLESS if they want. People doing Perl OO understand SUPER:: already. -Nate
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On 9/2/00 11:34 AM, Nathan Wiger wrote: It doesn't seem that it's that hard to add a single line to your SETUP or BLESS or whatever method that calls SUPER::SETUP. I'm pretty sure one of the big points about the system described is that it ensures both that there's always a predictable and automatic chain of events for SETUP/DESTROY (without requiring the programmer to create and document his own bug-free implementation) and it ensures that each routine is called only once, regardless of multiple inheritance paths. And I still vote for BUILD, SETUP, or MAKE over BLESS. The whole notion of blessing is non-obvious enough already. But bless() does the blessing. Those chained routines do the INITing, or the BUILDing, or the SETUP. They don't do the blessing. I think the conceptual hurdle for newbies will be the order of dispatch, not the name of the routine that get called after blessing. Naming it BLESS too greatly favors the first week of Perl use, punishing experienced programmers by making them do all their setup and initialization in routines with a fanciful and illogical name. After several years of this, we'd see 50 Perl 7 RFCs about renaming BLESS to BUILD, SETUP, or MAKE. Mark my words! ;) Actually, I'd be happy with an RFC for an entirely new method of object creation and identification that has nothing to do with bless (but I don't expect one and I'm not clever enough to come up with something myself that'd sway the Perl public...) -John
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
The whole notion of blessing is non-obvious enough already. It's the benedictory (con)not(at)ion of blessing, not the bless()ing itself that so confuses people, I think. It bless() were instead named something like mark stamp label brand retype denote notate entype mktype nominate emblazon classify annotate designate authorize methodize This might not be so confusing. Most of those, however, are longer to type than bless. --tom
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
I'm still not totally convinced that its so horrid to make the File::LockAndKey DESTROY call $self-SUPER::DESTROY manually... Believe me, it is in a large, deep, and/or MI hierarchy! but it does break encapsulation. Exactly. If you can figure a way out of the dilema I proposed above, I suppose this makes sense. Easy. Don't let File::Lock::Mac inherit from File::Lock. Have it *delegate* to File::Lock instead. See my forthcoming Cuse delegation RFC. Damian
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On Sat, Sep 02, 2000 at 03:18:06PM -0400, Mike Lambert wrote: In certain cases, like the one in which you proposed, you'd want to explicitly bypass the parent DESTROY. sub DESTROY { my $self = shift; $self-UNIVERSAL::DESTROY(@_); } would skip the automatic chaining because the function contains an explicit call to a superclass's DESTROY. As you said, sounds difficult to implement and difficult to document. Too much magic. In cases of more complex class hierarchies, you can explicitly call one parent class's DESTROY, and skip anothers. Bad, bad, bad. Busts encapsulation, poking around in your parent's hierarchy. Just to make it clear, I agree, in principle, with chaining DESTROY and SETUP. I'd just like to see all the caveats cleared away first. We already have a system that kinda works, there's no point in replacing it with another that only kinda works. Also, its not entirely clear why method chaining is desired only for constructor and destructors. What about every other method? -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse BOFH excuse #177: sticktion
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
Also, its not entirely clear why method chaining is desired only for constructor and destructors. What about every other method? Constructors and destructors are special. They're not about *doing* something; they're about *being* (or not being) something. A "doing" method *may* wish to make the object do everything its hierarchy allows it to do: that's why I proposed CNEXT. A "being" method *must* make the object be everything its hierarchy requires it to be: that's why I proposed hierarchical constructors and destructors. Damian
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On 9/1/00 5:44 PM, Nathan Wiger wrote: sub SETUP { my ($self, @ctor_data) = @_; # initialization of object referred to by $self occurs here } Hmmm. I'm not sure if I like this. I like the *idea* a lot, but I must say that I think I quite like RFC 171's approach better. I haven't commented on RFC 171 because I assumed it would be shot down quickly by the Major Contibutors(tm), but let me just say now that I'm firmly in this camp: On 9/1/00 5:58 AM, Bart Lateur wrote: If you want a constructor called, than FGS *call* a constructor. Maybe you can reduce the syntax necessary to do that, but please don't do it behind our backs. And I'll further add that I like Damian's RFCs on the topic, having essentially duplicated that functionality "by hand" myself at various times, and found it to be very useful and friendly. (Although I used "init" instead of "SETUP" but I guess there already is an "INIT") -John
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On Fri, Sep 01, 2000 at 08:59:10PM -, Perl6 RFC Librarian wrote: =head1 ABSTRACT This RFC proposes a new special method called CSETUP that is invoked automagically whenever an object is created. Furthermore, it proposes that both CSETUP and CDESTROY methods should be invoked hierarchically in all base classes. I agree with Michael that SETUP should be BLESS. You argue that it "doesn't do any blessing", ignoring Michael's point about PRINT not (necessarily) doing any printing. As you pointed out in the 'MIGRATION' section, such a radical change to the meaning of DESTROY [w]ould have serious impact. I contend that a name other than DESTROY should be chosen for recursive-destructor role. I like CURSE, though maybe ABSOLVE will better please the unperverted among us. Then object reblessing would naturally call CURSE via the old package and BLESS with the new. If reblessing is not itself condemned, that is. use base map { "Base$_" } 1 .. 999; { my $x = bless {}; # a thousand blessings }# a thousand curses (m+s vs refcounting aside) =head2 The CSETUP method It is proposed that, if a class has a method named CSETUP, that method will be invoked automatically during any call to Cbless. It is further proposed that Cbless be extended to take an optional argument list after its second argument, and that this list would be passed to any CSETUP method invoked by the Cbless. Every base's SETUP gets the same argument list? That seems highly undesirable from an OO-purity standpoint. Or do you have a syntax for member initializer lists in store for us? Better, have UNIVERSAL::new load the args into a hash and pass it to SETUPs by reference, avoiding positional-parameter hell. SETUP can delete what it processes and insert what its bases need. UNIVERSAL::new can even warn about "unrecognized initializer arg" if there's anything left in the hash when SETUPs have finished. See my experimental UNIVERSALs below. Note that CBase2::DESTROY is only called once (as late as possible), even though class Rederived inherits it through two distinct paths. Let's get the single-inheritance case nailed down before we think about how it should work in MI. With Perl's interface inheritance (a term for which I thank you, Damian), who knows? Maybe some base classes don't want to be virtual. =head2 Proposed standard CUNIVERSAL::new Given that most Perl classes are hash-based and that the CSETUP method cleanly separate construction and initialization, it might be desirable to have the UNIVERSAL class always supply a default constructor: package UNIVERSAL; sub new { bless {}, @_ } Yes, and it could call SETUP the way you want, eliminating the need to change the 'bless' builtin. There could even be a UNIVERSAL::SETUP that looks for args from %FIELDS (or its successor) in its initalizer hash. Below is something along these lines that I put together last year. It relies on pseudohash semantics, but the principles are what's of interest. package JTobey::UNIVERSAL; sub new { if (scalar(@_) =~ /[02468]$/) { require Carp; Carp::confess ("Missing value for last initializer"); } my ($pkg, %args) = @_; my ($obj, $fields); { no strict 'refs'; $fields = \%{"$pkg\::FIELDS"}; } $obj = bless [$fields], $pkg; $obj-init (\%args); if (%args) { require Carp; Carp::croak ("Initializer list contains unrecognized fields: " .join(", ", keys %args)); } return $obj; } sub init { my ($obj, $argsref) = @_; my ($fields, $pos); $fields = $$obj[0]; foreach my $name (keys %$argsref) { next if not $pos = $$fields{$name}; $$obj[$pos] = delete $$argsref{$name}; } } # Break circular references. sub free { @ { $_[0] } = (); } -John