in reply to Should a constructor ever return undef?

This is the general problem of resource acquisition. Sometimes you cannot test beforehand to see if an operation will succeed. The only way to know it to go ahead and try it.

For instance, even in your constructor, although you test for the existence of a directory with -e (although personally I would test with -d), you cannot be sure that it isn't deleted or renamed between the time you test it and the time you use it. The chance is vanishingly small, but it is non-zero.

C++ constructors don't make a separation between acquisition and initialisation, and you are soundly flamed in C++ circles if you propose

foo_t foo = new Foo('/path/to/dir'); foo.init();

... the main complaint being that when foo is constructed it's ready for service ("what happens if the client forgets to call init()?" is the common observation).

If a constructor fails, or can only partially initialise the object, there is no out-of-band channel to communicate this fact. To get around this problem was one of the main motivations for adding exception handling to the language.

I quite like the fact that Perl object construction works the way it does; that it doesn't require exception handling in the simple case. Remember the dictum "Perl makes the easy things easy."

You're quite comfortable with checking the result of an open or system (... well... you should be), so it should seem natural that you check the results of creating objects too. With the "do or die" idiom, it's quite easy to get the die part of the code out of the way, much cleaner than checking malloc and open in C, where the error checking drowns out the main action.

_____________________________________________
Come to YAPC::Europe 2003 in Paris, 23-25 July 2003.

Replies are listed 'Best First'.
Re: Re: Should a constructor ever return undef? (yes)
by tall_man (Parson) on Jul 11, 2003 at 15:10 UTC
    Ok, it looks like the consensus of most of the answers is that returning undef is normal. But I'd still like to make it harder for the unwary programmers to forget to check the return. I'm suggesting to my co-workers that constructors that can return undef be named "fallible_new" instead of just "new". That might be a little obnoxious, but it would help prevent bugs.
      Ok, it looks like the consensus of most of the answers is that returning undef is normal.

      Just because something is commonly accepted doesn't mean it's good ;-)

      But I'd still like to make it harder for the unwary programmers to forget to check the return.

      You might want to look at using the Fatal module. You can use this to force an exception to be thrown if undef is returned.

      However, if returning a false value on failure is actually causing problems for you I would strongly consider moving over to an exception throwing style.