Документация
HTML CSS PHP PERL другое

Section 13.3.  Contextual Failure

 
Previous
Table of Contents
Next

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.

    Previous
    Table of Contents
    Next
    © 2000- NIV