Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler [EMAIL PROTECTED] writes: On Mon, Sep 04, 2000 at 10:34:37AM +0100, Piers Cawley wrote: Well then, that's one nay vote. :) Make that two. Three. But I think Michael already knew about mine and forgot to count it. Heh, I am not counting votes. That was simply me acknowledging his dislike for the idea. I wish you guys would stop, too; you're depressing me. Well, you keep advancing this idea which has, as far as I can tell, no upside apart from the reduction in keystrokes required to instantiate an object. And in doing that you remove useful functionality from a bunch of other cases. No wonder we're down on the idea. -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Well, unless there are any wildly different points someone hasn't mentioned until now, I'm going to freeze this RFC as it is (with a few minor tweaks). Various alternate syntaxes have been suggested, but I still rather like mine. Let Larry do with it what he will. Hopefully he can take something useful from the suggestion, and the ensuing discussion. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler [EMAIL PROTECTED] writes: On Fri, Sep 01, 2000 at 10:22:49AM +0100, Piers Cawley wrote: And then there's: - Makes factory methods impossible. my Dog $spot; my $pub = $spot-procreate; Sure looks like a factory method to me. Just because you don't get to say my Dog $pup for some optimization doesn't mean they're impossible. Given that Cmy Dog $pup would appear to be (currently) the only way to get any optimization at compile time then I submit that the ability to optimize all method calls at compile time by declaring typed variables for stuff is *far* more important than the questionable gains to be had from implicit instantiation. I can think of *far* more occasions where I want the optimization than occasions where I don't. Maybe a compromise along the lines of: my Dog $spot = LIST; # $spot = Dog-new(LIST) my Dog $patches; # $patches is undefined but we assert that # it'll be a Dog. (Whether you can do # $patches-new is left as an exercise) Where the first element of LIST is not a Dog. If you want to autocreate a null object then you can do Cmy Dog $spot = () - Conveniently forgets all about polymorphism. package Mammal; sub hair_color { ... } package Dog; use base qw(Mammal); sub CREATE { bless({}, "Dog") } package main; my Dog $spot; $spot-hair_color("blue"); # works just fine That's not polymorphism, that's inheritance. Polymorphism is: try { } catch Exception::SelfHandler { $!-handle_self } Note that in this context CException::SelfHandler is an abstract superclass. The precise behaviour of the handler is defined by its subclasses. Another example: package MailorderPetshop; sub make_ad { my MailorderPetshop $self = shift; $self-stock_iterator-reset; try { STOCKLOOP: while (my Pet $pet = $self-stock_iterator-next) { print $pet-describe, "\t", $pet-price; } } catch Exception::WrongType { # Oops, we're not looking for cages etc, skip that next STOCKLOOP; } } Again, the various C$pets are instances of classes which are subclasses of Pet, but in the context of the Cmake_ad all we care about is that they are pets. I'm not proposing revamping the entire OO system, and I'd like to know what made you think I was. No, but you are proposing the removal of a behaviour which has the potential to be *very* useful when it gets better optimized, in favour of something of questionable benefit. However, see my suggestion at the top of this reply for something that may prove to be a useful compromise. Also, if you're really proposing this as a way of saving typing, consider the idea that got floated on p5p a while back: use shortcut; with Long::Package::Base; my ::Dog $spot = ::Dog-new('Fido'); Which has the advantage of being useful all over the place... -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler [EMAIL PROTECTED] writes: On Sun, Sep 03, 2000 at 12:42:52PM +0200, Bart Lateur wrote: But now you're throwing away the kid with the bathwater. my Dog $spot; initially was syntax invented so that $spot was marked as only been ably to reference a Dog, with as a result that code internally could be optimized, by doing things at compile time why otherwise would need to be dealt with at runtime. (use fields, as the most notable example). Don't throw that away. Just to be clear, I'm not throwing it away. Nothing's preventing the compiler from still doing that optimization. I'm simply tacking on additional meaning, that it creates a Dog object out of $spot. You are throwing it away because your proposal means we don't get to use the optimization in a whole bunch of places where we could before. -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Nathan Wiger [EMAIL PROTECTED] writes: Piers Cawley wrote: First off, I think everyone is reading this RFC with the wrong mindset, forgetting the concept of embedded objects in Perl 6. Ah, that dumb idea again. Well, if you disagree with this idea, you probably won't agree with much else I have to say on this subject. Just calling something "dumb" isn't very productive, though. Maybe an explanation of *why* you think it's "dump"? Who knows, you might convince me and all the other "loons" that want vtable stuff in core... Ah... light dawns... from reading further down I think I finally understand where you're coming from with that RFC and it's not as dumb as I thought it was, though I still wonder what happens when you assign a 'Dalmation' to a 'Dog' shaped variable. But you're creating the wrong bloody thing. And then you're throwing it away. Now that's what I call a win. In this scenario what will my Dog $spot; print defined($spot) return? If it's *not* 'undef' there'd better be a bloody good reason This should definitely return undef. That's not the impression I got from reading Michael's RFC. See that my Dog $patches = $dog_factory-make_me_a_dog That's a factory method that is, returns a Dog of some sort, but you don't know of what breed. Ok, then again I don't see what your problem with this RFC is. Because Cref($patches) could easily be 'Dalmation'. Maybe Michael and I are on different wavelengths, Actually, I think you may be. so I don't want to rewrite his RFC involuntarily through this discussion. *MY* take on CREATE is that it's all taken care of for you, unless you override it, in which case you can do special stuff. Increased flexibility, but doesn't get in the way. Don't use it if you don't want to. Just like DESTROY. -Nate
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Damian Conway [EMAIL PROTECTED] writes: But I agree that anything beyond that is simply horrible. You'll only drive more people *away* from OO, because it generates so horribly inefficient code. 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. Well then, that's one nay vote. :) Make that two. Three. But I think Michael already knew about mine and forgot to count it. -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler [EMAIL PROTECTED] writes: On Fri, Sep 01, 2000 at 05:23:27PM +0200, Slaven Rezic wrote: Often, there is the case that "my" is used before actually assigning a value to it. For example: my Foo $foo; if ($cond1) { $foo = new Foo 1, 2, 3; } else { $foo = new Foo 2, 4, 6; } If we have implicit constructors, will this cause unnecessary overhead, that is, calling the implicit constructor and then the real one? Yes, so don't do that. If you want optimization, I've been suggesting my $spot : isa(Dog) (actually, I've been suggesting my $spot isa(Dog), which was a typo): But that's *so* ugly for the (In my code at least) more common case. If all you want this behaviour for is to save typing, what about simply *extending* the current syntax so you'd one of: my new Dog $spot;# Not sure the parser'd like that. my Dog $spot : from(new); # same as 'my Dog $spot = Dog-new Actually, I kind of like the second one (though I'm not sure 'from' is the right name) as it allows you to specify the appropriate constructor. The advantage of this is that the existing syntax still works so that those of us who are already using it in anticipation of the glorious day when we finally get some optimization from it won't have to rethink the way we do things. Okay, if you want the new behaviour you have to learn the new syntax, but hey, that's why it's new. -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, 1 Sep 2000 11:59:15 -0800, Michael Fowler wrote: my Dog $spot; if ($input eq 'Collie') { $spot = Collie-new; } elsif ($input eq 'Dalmation') { $spot = Dalmation-new; } Becuase we're creating two objects when we really only want one. Yes. That my Dog $spot should be either my $spot or my $spot : isa(Foo) (which I just recently made up) in this case. But now you're throwing away the kid with the bathwater. my Dog $spot; initially was syntax invented so that $spot was marked as only been ably to reference a Dog, with as a result that code internally could be optimized, by doing things at compile time why otherwise would need to be dealt with at runtime. (use fields, as the most notable example). Don't throw that away. Your proposed isa(Dog) syntax is supposed to replace that syntax, while the old syntax would get new functionality. It doesn't look nice, for a start. The idea breaks the "if it does something else, give it a new name" rule. How about: my new Dog $spot; which creates a new instance of Dog, while my Dog s$pot; doesn't. -- Bart.
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Sun, Sep 03, 2000 at 12:42:52PM +0200, Bart Lateur wrote: But now you're throwing away the kid with the bathwater. my Dog $spot; initially was syntax invented so that $spot was marked as only been ably to reference a Dog, with as a result that code internally could be optimized, by doing things at compile time why otherwise would need to be dealt with at runtime. (use fields, as the most notable example). Don't throw that away. Just to be clear, I'm not throwing it away. Nothing's preventing the compiler from still doing that optimization. I'm simply tacking on additional meaning, that it creates a Dog object out of $spot. It's been something of a struggle to word the RFC correctly so that it properly conveys that the old usage of my Dog $spot won't work as used currently, but the optimization can still be done. Does that make any sense? Your proposed isa(Dog) syntax is supposed to replace that syntax, while the old syntax would get new functionality. It doesn't look nice, for a start. The idea breaks the "if it does something else, give it a new name" rule. How about: my new Dog $spot; That's definitely an alternative. I don't particularly like it, but it's an alternative. That is, assuming we all (or at least, most of us) want an implicit construction mechanism. From the discussion, that doesn't seem to be the case. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Sat, 2 Sep 2000, Nick Ing-Simmons wrote: Damian Conway [EMAIL PROTECTED] writes: But I agree that anything beyond that is simply horrible. You'll only drive more people *away* from OO, because it generates so horribly inefficient code. 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. Well then, that's one nay vote. :) Make that two. Three. I was hoping to be strike three! Four. David
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 12:20:34PM +0100, Hildo Biersma wrote: Michael Fowler wrote: On Fri, Sep 01, 2000 at 08:31:17AM +0100, Hildo Biersma wrote: My previous concerns have not been adressed: - There may not be a default constructor If there is no implicit constructor method defined by the class, and the my Dog $spot syntax is used, a fatal exception is raised. The RFC mentions this. This exact thing is also currently being discussed. In OO vocabulary, a 'default constructor' is one that has been declared to take no arguments. If a class defines a constructor that requiers arguments, it cannot be called implicitly. This is not true. In C++, if a class constructor that requires a single argument is defined, and without the keyword explicit, it can be called implicitly in type conversions. However, I fail to see how this definition of 'default constructor' makes it a requirement that there be one. There must be one for my Dog $spot to not raise a fatal exception, but if it's not defined and my Dog $spot is never used, there is no requirement that there be an implicit constructor. - This makes creations of Singleton classes impossible In what way? The implicit constructor method can return anything it likes, just as current constructors can. Singleton classes can have a private constructor, and a class method that conditionally invokes the constructor _once_, then re-uses the reference when this makes sense. That does not make the class method the constructor - and there might be multiple, different, of these class methods. my Dog $spot does not preclude the use of explicit constructors. All it does is call a constructor implicitly. I guess I still fail to see how this makes singleton classes any less possible than current Perl makes them. - There is a good reason to created typed, but undef, references and fill them in later. What is this reason? Can you give some examples? You need to be able to create a scoped and typed object reference that starts out undefined, then is filled in depending on various arguments, and then is used safely afterwards. sub BuyDog { my ($budget, $age) = @_; my Dog $retval; if ($budget 100) { $retval = ExpensiveDog-new( blabla ---); } elsif ($age 12) { $retval = BigDog-new(--- blabla ---); } else { $retval = MangyDog-new(--- blabla ---); } $retval-feed(); fill_in_forms($retval); return $retval; } Could such a thing fit cleanly and unambiguously in with the rest of this idea? If so, do you have an idea how? I think not - creating objects implicitly is *wrong*, unless we start to allow creating Objects on the stack, such as C++ does. Well, I've been giving examples of using: my $spot isa(Dog); today. This does fit cleanly and unambiguously. As for creating objects implicitly, this doesn't do that. The constructor is called implicitly, the my Dog $spot syntax is fairly explicit. Based on my C++ experience, this should only be allowed if the constructor has been marked as 'implicit construction safe'. It is assumed that the method is "implicit construction safe", if by that you mean suitable to be called implicitly to construct an object. Since the methods are uniquely named, or specified by the author, I don't think this is assuming too much. Let me reiterate. One of the issues in C++ is that Dog spot = 5; means Dog spot = Dog(5); Actually, it's: Dog spot; spot.overload=(5); assuming there's an operator=(int) defined. If there's only a Dog(int) defined, and an operator=(Dog), then yes, the 5 is implictly converted. I am not proposing we implement implicit conversions. Merely naming a method as a constructor does not mean implicit object creation is a good idea. Creating objects can be quite expensive, and one of the biggest drags on program performance is unexpected object creation. Is getting an object out of my Dog $spot unexpected? What about if you were to forget what my Dog $spot means currently? Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 05:23:27PM +0200, Slaven Rezic wrote: Often, there is the case that "my" is used before actually assigning a value to it. For example: my Foo $foo; if ($cond1) { $foo = new Foo 1, 2, 3; } else { $foo = new Foo 2, 4, 6; } If we have implicit constructors, will this cause unnecessary overhead, that is, calling the implicit constructor and then the real one? Yes, so don't do that. If you want optimization, I've been suggesting my $spot : isa(Dog) (actually, I've been suggesting my $spot isa(Dog), which was a typo): my $foo : isa(Dog); if ($cond1) { $foo = new Foo 1, 2, 3; } else { $foo = new Foo 2, 4, 6; } Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 11:41:47AM -0700, David E. Wheeler wrote: Michael Fowler wrote: my Dog $spot; # $spot is now a blessed Dog object $spot-name("Fido");# $spot-{'name'} eq "Fido" print ref $spot;# yes, "Dog" $spot = new Dalmation; # now $spot is a Dalmation object Yes, but the Dalmation $spot will *not* have the name "Fido," will it? Nope, $spot is now an entirely new object. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 10:58:36AM -0800, Michael Fowler wrote: my $spot isa(Dog); This should be my $spot : isa(Dog); Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 09:09:15AM -0700, Nathan Wiger wrote: First off, I think everyone is reading this RFC with the wrong mindset, my Dog $spot; print ref $spot;# 'Dog' $spot = new Dalmation; No reason this wouldn't still work. The term 'constructor' here is misleading. 'creator' is what I prefer, and that's also why I prefer CREATE. It will work, but not the way you're expecting (I don't think). Given: package Dog; sub CREATE { bless({ name = undef }, shift) } sub name { my $self = shift; if (@_) { return $self-{'name'} = shift; } return $self-{'name'}; } I've annotated what the code does: my Dog $spot; # $spot is now a blessed Dog object $spot-name("Fido");# $spot-{'name'} eq "Fido" print ref $spot;# yes, "Dog" $spot = new Dalmation; # now $spot is a Dalmation object At least, this is my take on it. CREATE would border right on the edge of internals, taking care of stuff that you normally wouldn't handle with new() anyways. Since it's a sub, you can put whatever you want into it, but CREATE != new() philosophically. Unfortunately (because everyone seems to disagree with me) CREATE (or PREPARE, or NEW, or author-defined) is new(). And of course, Me != Michael, so I don't want to put too many words in his RFC. However, this is my take on it. I'm writing a massive RFC right now that tries to tie this all together. It's actually quite coherent, but when little bits and pieces are leaked admittedly it sounds disjointed. Well, I guess I'll wait until that RFC comes out before asking you what CREATE does, exactly, in your world. :) Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler wrote: On Fri, Sep 01, 2000 at 11:41:47AM -0700, David E. Wheeler wrote: Michael Fowler wrote: my Dog $spot; # $spot is now a blessed Dog object $spot-name("Fido");# $spot-{'name'} eq "Fido" print ref $spot;# yes, "Dog" $spot = new Dalmation; # now $spot is a Dalmation object Yes, but the Dalmation $spot will *not* have the name "Fido," will it? Nope, $spot is now an entirely new object. Well then, that makes this example rather wasteful, doesn't it? my Dog $spot; if ($input eq 'Collie') { $spot = Collie-new; } elsif ($input eq 'Dalmation') { $spot = Dalmation-new; } Becuase we're creating two objects when we really only want one. David
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 12:35:24PM -0700, David E. Wheeler wrote: Well then, that makes this example rather wasteful, doesn't it? It wasn't an example of how my Dog $spot should be used. I was explaining to Nate what his code was doing. my Dog $spot; if ($input eq 'Collie') { $spot = Collie-new; } elsif ($input eq 'Dalmation') { $spot = Dalmation-new; } Becuase we're creating two objects when we really only want one. Yes. That my Dog $spot should be either my $spot or my $spot : isa(Foo) (which I just recently made up) in this case. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Fri, Sep 01, 2000 at 10:22:49AM +0100, Piers Cawley wrote: And then there's: - Makes factory methods impossible. my Dog $spot; my $pub = $spot-procreate; Sure looks like a factory method to me. Just because you don't get to say my Dog $pup for some optimization doesn't mean they're impossible. - Conveniently forgets all about polymorphism. package Mammal; sub hair_color { ... } package Dog; use base qw(Mammal); sub CREATE { bless({}, "Dog") } package main; my Dog $spot; $spot-hair_color("blue"); # works just fine I'm not proposing revamping the entire OO system, and I'd like to know what made you think I was. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Bart Lateur wrote: First: I don't like the idea of some user supplied code being called whenever you declare a new variable, *unless* the author of the class created a sub *especially written* for this purpose. Exactly. Even then, the arguments must match. So, if Dog::new() takes one argument, and has also been declared to be the 'implicit constructor', then: my Dog $spot; is a syntax error. my Dog $spot = 'hungry'; is allowed. Suppose all you want is a variable that can reference existing Dog objects, I definitely do not want that a new object that I don't need is created, every time I get to the declaration. Do you really want: for (1..1000) { my Dog $spot; } to create 1 unused Dog objects? Ugh! (not "Ug") Agree. I think the RFC confuses the notion of object with the notion of reference. But I agree that anything beyond that is simply horrible. You'll only drive more people *away* from OO, because it generates so horribly inefficient code. 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. Agree. Either learn from C++ or don't go this route. Hildo
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Michael Fowler wrote: On Fri, Sep 01, 2000 at 08:31:17AM +0100, Hildo Biersma wrote: My previous concerns have not been adressed: - There may not be a default constructor If there is no implicit constructor method defined by the class, and the my Dog $spot syntax is used, a fatal exception is raised. The RFC mentions this. This exact thing is also currently being discussed. In OO vocabulary, a 'default constructor' is one that has been declared to take no arguments. If a class defines a constructor that requiers arguments, it cannot be called implicitly. - This makes creations of Singleton classes impossible In what way? The implicit constructor method can return anything it likes, just as current constructors can. Singleton classes can have a private constructor, and a class method that conditionally invokes the constructor _once_, then re-uses the reference when this makes sense. That does not make the class method the constructor - and there might be multiple, different, of these class methods. - There is a good reason to created typed, but undef, references and fill them in later. What is this reason? Can you give some examples? You need to be able to create a scoped and typed object reference that starts out undefined, then is filled in depending on various arguments, and then is used safely afterwards. sub BuyDog { my ($budget, $age) = @_; my Dog $retval; if ($budget 100) { $retval = ExpensiveDog-new( blabla ---); } elsif ($age 12) { $retval = BigDog-new(--- blabla ---); } else { $retval = MangyDog-new(--- blabla ---); } $retval-feed(); fill_in_forms($retval); return $retval; } Could such a thing fit cleanly and unambiguously in with the rest of this idea? If so, do you have an idea how? I think not - creating objects implicitly is *wrong*, unless we start to allow creating Objects on the stack, such as C++ does. Based on my C++ experience, this should only be allowed if the constructor has been marked as 'implicit construction safe'. It is assumed that the method is "implicit construction safe", if by that you mean suitable to be called implicitly to construct an object. Since the methods are uniquely named, or specified by the author, I don't think this is assuming too much. Let me reiterate. One of the issues in C++ is that Dog spot = 5; means Dog spot = Dog(5); which will always call Dog::Dog(int) (or a promotable version), unless this constructor has been marked 'explicit'. Many people feel this default should have been reversed: the constructor should only have been called if marked 'implicit', i.e. the default is wrong. Merely naming a method as a constructor does not mean implicit object creation is a good idea. Creating objects can be quite expensive, and one of the biggest drags on program performance is unexpected object creation. Hildo
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Often, there is the case that "my" is used before actually assigning a value to it. For example: my Foo $foo; if ($cond1) { $foo = new Foo 1, 2, 3; } else { $foo = new Foo 2, 4, 6; } If we have implicit constructors, will this cause unnecessary overhead, that is, calling the implicit constructor and then the real one? Regards, Slaven -- use Tk;$c=tkinit-Canvas(-he,20)-grid;$x=5;map{s!\n!!g;map{create$c 'line'= map{$a=-43+ord;($x+($a3)*2=5+($a7)*2)}split''}split"!";$x+=12}split/_/='K PI1_+09IPK_K;-OA1_+K!;A__1;Q!7G_1+QK_3CLPI90,_+K!;A_+1!KQ!.N_K+1Q!.F_1+KN.Q__1+ KN._K+1Q!.F_1+KN.Q_+1Q__+1!KQ!.N_1;Q!7G_K3,09Q_+1!K.Q_K+1Q!.F_1+KN.Q_';MainLoop
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Nathan Wiger [EMAIL PROTECTED] writes: First off, I think everyone is reading this RFC with the wrong mindset, forgetting the concept of embedded objects in Perl 6. Ah, that dumb idea again. I believe the idea would be that CREATE is a *fundamental* method, like DESTROY, that would do basic declaration, creation, allocation, etc. So: my Dog $spot; print ref $spot;# 'Dog' $spot = new Dalmation; No reason this wouldn't still work. The term 'constructor' here is misleading. 'creator' is what I prefer, and that's also why I prefer CREATE. But you're creating the wrong bloody thing. And then you're throwing it away. Now that's what I call a win. In this scenario what will my Dog $spot; print defined($spot) return? If it's *not* 'undef' there'd better be a bloody good reason, otherwise: package Hades; { my Dog $cerberus; #There can only be one sub get_guard_dog { $cerberus ||= Hellhound::ThreeHeaded-new(name = 'Cerberus'); return $cerberus; } } Doesn't work. Nor does any other creator of singletons come to that. - Makes factory methods impossible. A little clarification on what specifically constitutes a "factory method" would be great. See that my Dog $patches = $dog_factory-make_me_a_dog That's a factory method that is, returns a Dog of some sort, but you don't know of what breed. -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Piers Cawley wrote: First off, I think everyone is reading this RFC with the wrong mindset, forgetting the concept of embedded objects in Perl 6. Ah, that dumb idea again. Well, if you disagree with this idea, you probably won't agree with much else I have to say on this subject. Just calling something "dumb" isn't very productive, though. Maybe an explanation of *why* you think it's "dump"? Who knows, you might convince me and all the other "loons" that want vtable stuff in core... But you're creating the wrong bloody thing. And then you're throwing it away. Now that's what I call a win. In this scenario what will my Dog $spot; print defined($spot) return? If it's *not* 'undef' there'd better be a bloody good reason This should definitely return undef. See that my Dog $patches = $dog_factory-make_me_a_dog That's a factory method that is, returns a Dog of some sort, but you don't know of what breed. Ok, then again I don't see what your problem with this RFC is. Maybe Michael and I are on different wavelengths, so I don't want to rewrite his RFC involuntarily through this discussion. *MY* take on CREATE is that it's all taken care of for you, unless you override it, in which case you can do special stuff. Increased flexibility, but doesn't get in the way. Don't use it if you don't want to. Just like DESTROY. -Nate
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Hildo Biersma [EMAIL PROTECTED] writes: Perl6 RFC Librarian wrote: =head1 DESCRIPTION What is currently an optimization for pseudo-hashes: my Dog $spot = Dog-new(); should be replaced with: my Dog $spot; which calls an implicit constructor (discussed further in the IMPLEMENTATION section). The optimization behaviour can be retained in some form (see the MIGRATION section). My previous concerns have not been adressed: - There may not be a default constructor - This makes creations of Singleton classes impossible - There is a good reason to created typed, but undef, references and fill them in later. And then there's: - Makes factory methods impossible. - Conveniently forgets all about polymorphism. It's *horrible* I tell you. *HORRIBLE* -- Piers
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On 01 Sep 2000 10:22:49 +0100, Piers Cawley wrote: My previous concerns have not been adressed: - There may not be a default constructor - This makes creations of Singleton classes impossible - There is a good reason to created typed, but undef, references and fill them in later. And then there's: - Makes factory methods impossible. - Conveniently forgets all about polymorphism. It's *horrible* I tell you. *HORRIBLE* I haven't followed this discussion up too closely, as the subject doesn't really interest me. However, I have a few outsider remarks. First: I don't like the idea of some user supplied code being called whenever you declare a new variable, *unless* the author of the class created a sub *especially written* for this purpose. Suppose all you want is a variable that can reference existing Dog objects, I definitely do not want that a new object that I don't need is created, every time I get to the declaration. Do you really want: for (1..1000) { my Dog $spot; } to create 1 unused Dog objects? Ugh! (not "Ug") Furthermore, I think it would be rather neat if my Dog $spot; print ref $spot; would indeed print "Dog". But that is as far as it should go. At worst, in special cases (with "use Fields;", for example), it may be initialized to an empty but pre-keyed blessed "hash". Well, that is in the view of current class implementation practices. If the objects internals for Perl6 become radically different, these ideas should be But I agree that anything beyond that is simply horrible. You'll only drive more people *away* from OO, because it generates so horribly inefficient code. 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. -- Bart.
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
But I agree that anything beyond that is simply horrible. You'll only drive more people *away* from OO, because it generates so horribly inefficient code. 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. Well then, that's one nay vote. :) Make that two. Damian
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Thu, Aug 31, 2000 at 09:45:52PM -0600, Tom Christiansen wrote: Well, remember that BEGIN{} blocks are just subs too, with an optional 'sub'. Not exactly. They are not callable, as they disappear immediately. More importantly, they have no @_, and things like pop and shift act upon @ARGV from within them. The compilerish chapter of the Camel calls them blocks. Well this is good to know (and I should have known it, too). I will remove them as alternatives. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Besides, what would be the alternative, BEGIN{} - like blocks? Such blocks are put forth as an alternative: Well, remember that BEGIN{} blocks are just subs too, with an optional 'sub'. But that aside, I don't think a block is what we want to connote. A block implies "this is evaluated here", not "this is a member method". That's a sub. Maybe a special sub, like DESTROY, but it's still just a sub. Being able to call these as normal methods may be desirable, or it may not be. Personally, I will likely never call $spot-PREPARE, just as I never call tied(%ixhash)-STORE("foo" = "bar"). I want to be able to. I call -STORE and -DESTROY all the time, because it's faster than having to go through tie: $object = tie %ignoreme, 'Some::Class'; $object-STORE('key', 'val'); $object-DESTROY; So the object would be left undefined? That means this code: No, not at all. Remember, everything's going to inherit from CORE, at the very least, which would have to provide a CREATE method which just instantiates a simple object. So, if no Dog::CREATE exists, then $spot becomes a regular old scalar. I see many many uses for this. For example, maybe you have a class that you just want to add a STRING sub to, so it prints out nice. Forcing a CREATE sub to be defined here is a needless restriction. However, consider existing tied classes, for example IO::File; it must provide duplicate methods, lowercase for users, uppercase for the tied interface. Would it really be less consistent or readable if, say, the getline() method was able to be called when a user said either $fh, or $fh-getline? I'll soon have an RFC coming up that proposes a way to "fix" this, but implements it differently. I think you'll like it. I disagree vehemently that users should be able to name all this stuff. If they're really bothered by it, that's what typeglobs are for. Infinite flexibility == Infinite confusion. And I don't think simply choosing variable and sub names counts as dictating style. So on this point you and I will have to disagree. -Nate
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
Well, remember that BEGIN{} blocks are just subs too, with an optional 'sub'. Not exactly. They are not callable, as they disappear immediately. More importantly, they have no @_, and things like pop and shift act upon @ARGV from within them. The compilerish chapter of the Camel calls them blocks. --tom
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Thu, Aug 31, 2000 at 07:56:24PM -0700, Nathan Wiger wrote: So the object would be left undefined? That means this code: No, not at all. Remember, everything's going to inherit from CORE, at the very least, which would have to provide a CREATE method which just instantiates a simple object. Don't you mean UNIVERSAL, or did I miss an RFC? So, if no Dog::CREATE exists, then $spot becomes a regular old scalar. I see many many uses for this. For example, maybe you have a class that you just want to add a STRING sub to, so it prints out nice. Forcing a CREATE sub to be defined here is a needless restriction. How is a regular scalar any better than undef? It's actually worse, potentially creating bugs that are even more difficult to spot. my Dog $spot = "Spot"; # no CREATE, $spot is now just "Spot" $spot-type("collie"); # Spot-type("collie") ! If you meant a reference, that's even worse. Consider the DBI class; a user, neglecting to read the documentation, tries: my DBI $dbh ($database_dsn, $database_username, $database_password); my $sth = $dbh-prepare( ... ); $dbh was blessed into the DBI class, but as a simple scalar. Now the prepare method gets a scalar reference where it was expecting a hash reference. I know of few classes that test their object to see if it's the proper underlying reference, and I doubt DBI is any different. It tries to do something like $self-{'database_username'} and blows up rather spectacularly, and the user sees an error deep inside of DBI. If you meant a hash reference, there's a similar problem, though you'll see warnings instead of fatal errors. That is, assuming DBI uses a hash reference (which it does, last time I checked, but this is just an example). So, DBI is forced to provide a CREATE method if bugs are to be made easy to track. I would much rather the my DBI $dbh blow up then and there, so the user gets instant feedback that they shouldn't do that with DBI. DBI is a good example in another way; DBI-connect() returns a reference blessed into the DBI::db class. The default CREATE, if it returns a reference, can only think to bless it into the DBI class. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
First off, nice additions to the RFC. Listed below are constructor alternatives. If a sub is chosen (as in sub PREPARE {}) it will suffer from the disadvantage of potentially causing problems with current Perl modules. I don't really think this is a valid concern. We can have p52p6 warn them, and all other Perl stuff (tie's STORE/FETCH, Perl's DESTROY, etc) are already done by ALLCAPS subs, just like global vars are $ALLCAPS. Besides, what would be the alternative, BEGIN{} - like blocks? I think these should just be subs, that way the user can call them at will as well. It also makes the implementation easier, just call the appropriate sub if it exists. If an appropriate constructor is not provided a fatal exception should be raised when the syntax is used. Naw, I don't think we should go this route. If it's not a valid imported package, then the statement should die. But not defining a constructor should only yield a warning with -w: No implicit constructor defined by package Dog at line 47. At the very most. This definition would probably be best provided through a pragma: use constructor qw(new); I also don't think we should do this. There's nothing more special about CREATE/PREPARE/NEW than DESTROY, STORE, or FETCH. We should provide what we think is a good name (and perhaps some alternatives), and let Larry decide. I'm very much against allowing people to tweak absolutely everything. There are minimal gains for marked losses in consistent, readable, maintainable code. See this link for a rant on how this can go really bad really quickly: http://www.mail-archive.com/perl6-language-objects%40perl.org/msg00131.html -Nate
Re: RFC 171 (v2) my Dog $spot should call a constructor implicitly
On Thu, Aug 31, 2000 at 05:15:34PM -0700, Nathan Wiger wrote: First off, nice additions to the RFC. Thanks. :) Listed below are constructor alternatives. If a sub is chosen (as in sub PREPARE {}) it will suffer from the disadvantage of potentially causing problems with current Perl modules. I don't really think this is a valid concern. We can have p52p6 warn them, and all other Perl stuff (tie's STORE/FETCH, Perl's DESTROY, etc) are already done by ALLCAPS subs, just like global vars are $ALLCAPS. You don't consider warnings from an otherwise working module a problem? I do. It's an issue, and should be mentioned. Besides, what would be the alternative, BEGIN{} - like blocks? Such blocks are put forth as an alternative: =item sub PREPARE {} or PREPARE {} I think these should just be subs, that way the user can call them at will as well. It also makes the implementation easier, just call the appropriate sub if it exists. Being able to call these as normal methods may be desirable, or it may not be. Personally, I will likely never call $spot-PREPARE, just as I never call tied(%ixhash)-STORE("foo" = "bar"). If the module is intended to have such things explicit methods should be provided, preferably lowercase ones. That is not to say PREPARE (or whatever is chosen) should not be a sub, I'm just questioning the practice of calling them directly. If an appropriate constructor is not provided a fatal exception should be raised when the syntax is used. Naw, I don't think we should go this route. If it's not a valid imported package, then the statement should die. But not defining a constructor should only yield a warning with -w: No implicit constructor defined by package Dog at line 47. At the very most. So the object would be left undefined? That means this code: my Dog $spot; ... intervening space ... $spot-collar("studded"); emits a warning when there's no Dog-$METHOD, and then promptly dies when you try to call a method on an undef object. The two constructs could be quite a distance apart. I would rather have a fatal error at the source, not the symptom. This definition would probably be best provided through a pragma: use constructor qw(new); I also don't think we should do this. There's nothing more special about CREATE/PREPARE/NEW than DESTROY, STORE, or FETCH. We should provide what we think is a good name (and perhaps some alternatives), and let Larry decide. Which is what I'm doing. I'm providing alternatives, including one where the module author is allowed to name the implicit constructor. :) I'm very much against allowing people to tweak absolutely everything. There are minimal gains for marked losses in consistent, readable, maintainable code. See this link for a rant on how this can go really bad really quickly: Sure, taken to the extreme, anything can be bad. There is more than a little ugly Perl code out there (*gasp* blasphemer!) because some programmers take certain features and idioms to the extreme. The same can be said of any language. However, consider existing tied classes, for example IO::File; it must provide duplicate methods, lowercase for users, uppercase for the tied interface. Would it really be less consistent or readable if, say, the getline() method was able to be called when a user said either $fh, or $fh-getline? I'd say do both; provide some default method, and provide a way to specify it when it makes sense. Michael -- Administrator www.shoebox.net Programmer, System Administrator www.gallanttech.com --