Section 13.3. Contextual Failure


13.3. Contextual Failure

Make failures fatal in all contexts.

The Fatal pragma can also be invoked with the special marker :void. Loading Fatal with this extra marker causes it to rewrite builtins and subroutines in a slightly different way, such that they throw a failure exception only if they were called in a void context. Under :void, they continue to silently return false in non-void contexts. That is:

     use Fatal qw( :void open close );     if (open my $out, '>', $filename) {         # Call to open(  ) in non-void context so                                                 #     open(  ) returns false on failure         open my $in, '<', '$filename.dat';      # Call to open(  ) in void context so                                                 #     open(  ) throws exception on failure         print {$out} <$in>;         close $out                              # Call close(  ) in non-void context so             or carp "close failed: $OS_ERROR";  #     close(  ) returns false on failure         close $in;                              # Call close(  ) in void context so                                                 #     close(  ) throws exception on failure     }

While this may seem like an improvement (more flexible, more Perlish), it's actually a step backwards in terms of code reliability. The problem is that it's far too easy to call a subroutine or function in a non-void context and still not actually test it. For example:

          # Change unacceptable failure behaviour to throw exceptions instead...     use Fatal qw( :void locate_and_open );     # and later...     for my $filename  (@source_files) {         my $fh = locate_and_open($filename);         my $head = load_header_from($fh);         print $head;     }

Here, locate_and_open( ) is upgraded to throw exceptions on void-context failure. Unfortunately, it isn't called in a void context. It's called in scalar context, so it still returns its usual undef-on-failure. But, once again, the return value isn't subsequently checked.

Non-void context doesn't always imply a test, so a use Fatal qw( :void funcname ) may make your code appear to be more robust, without actually making that code more robust...which makes that code less robust.



Perl Best Practices
Perl Best Practices
ISBN: 0596001738
EAN: 2147483647
Year: 2004
Pages: 350
Authors: Damian Conway

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net