You don't even think timely, well-ordered destructors are important. So what do you know? ;)
Meow :-)
The idea is very DWIM and so I think it fits well with Perl.
It is an cute hack and I like the concept. However, unless I am misunderstanding your proposal there are areas where it can cause non-obvious behaviour - unless you're careful.
For example, assuming method_that_fails returns an error object like the one you outlined:
{
# Would I expect a scope change to radically alter the time an
# error is reported?
# $x dies at the end of the block
# $y dies at some indeterminate time in the future.
my $x = Foo->new->method_that_fails->foo;
our $y = Foo->new->method_that_fails->foo;
};
# This will fail silently because $bar is an error object, $bar->next
# will just return $self, which is then evaluated in a boolean context
# so the DESTROY won't give an error. Would I remember to catch the
# error explicitly in situations like this? What if that while loop
# was off in another module?
my $bar = $foo->method_that_fails
while ($bar->next) { print $bar->current, "\n" };
# Would I expect an error about Foo creation when Bar objects
# are destroyed?
sub Bar::new {
bless {
foo => Foo->new->method_that_fails
}, shift
};
I know that we had this conversation before but the scoping issue didn't occur to me then. It seems fairly easy to come up with scenarios where the error object doesn't get DESTROYed for quite some time.
I can see this, in combination with AUTOLOADed methods returning the error object, resulting in errors being ignored or reported a long way from where they occurred.
As is, exception handling in Perl is what I consider to be an "uncommon practice" and likely to surprise people so I usually avoid it
Personally I find that exceptions help more than they hinder. I like keeping the error handling from obscuring the mainline. I've made my arguments for exceptions elsewhere so I won't repeat myself here ;-) YMMV.
Because Perl has timely destructors, I don't mind using them. I find them very powerful. There are things that can be done very cleanly in timely destructors that are just plain hard to do without
Agree completely. I use them myself on occasion.
The idea of not having well-ordered destructors just boggles my mind. But that is for another thread.
The idea of not having some sort of scoped action/finalization mechanism in a language boggles my mind. I just don't think it needs to be duct taped to an otherwise, for me, bleeding annoying memory management system :-)
I also find the distinction between exception and failure (so return a false value) to be a pretty slippery one.
It is an interesting distinction. It's not so much between exception and failure as between expected and erroneous behaviour. Is the fact that open returns false an error ("You asked me to open this and I can't. Ack!") or an informative return value ("You asked me to open this if I could and I couldn't. Just thought I'd let you know."). As you correctly point out it's context dependent.
One of my favorite things about this idea is that I don't have to decide. I enable you, the module user, to decide which one you want to use and to change your mind depending on the situation.
It is a nice idea but I think there are enough (pardon the pun) exceptions to the DWIMish behaviour to make the error object you suggested more trouble than it's worth.
I really think all Perl's built-in functions should be capable of behaving this way (like use Fatal qw( :void ... ) almost does) at least optionally.
Amen. I was so happy when I first discovered Fatal. Then sad to find all the cases where it doesn't work. Hey ho.
|