Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors

2000-09-02 Thread John Tobey

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

2000-09-02 Thread Nathan Wiger

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

2000-09-02 Thread John Siracusa

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

2000-09-02 Thread Tom Christiansen

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

2000-09-02 Thread Damian Conway

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

2000-09-02 Thread Michael G Schwern

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

2000-09-02 Thread Damian Conway

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

2000-09-01 Thread John Siracusa

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

2000-09-01 Thread John Tobey

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