views:

111

answers:

2

I tried to catch a carp-warning:

 carp "$start is > $end" if (warnings::enabled()); ) 

with eval {} but it didn't work, so I looked in the eval documentation and I discovered, that eval catches only syntax-errors, run-time-errors or executed die-statements.

How could I catch a carp warning?

#!/usr/bin/env perl
use warnings;
use strict;
use 5.012;
use List::Util qw(max min);
use Number::Range;

my @array;
my $max = 20;
print "Input (max $max): ";
my $in = <>;

$in =~ s/\s+//g;
$in =~ s/(?<=\d)-/../g;

eval {
    my $range = new Number::Range( $in );
    @array = sort { $a <=> $b } $range->range;
};
if ( $@ =~ /\d+ is > \d+/ ) { die $@ }; # catch the carp-warning doesn't work 

die "Input greater than $max not allowed $!" if defined $max and max( @array ) > $max;
die "Input '0' or less not allowed $!" if min( @array ) < 1;
say "@array";
+3  A: 

carp does not die but just prints a warning, so there's nothing to catch with eval or whatever. You can, however, overwrite the warn handler locally to prevent the warning from being sent to stderr:

#!/usr/bin/env perl

use warnings;
use strict;

use Carp;

carp "Oh noes!";

{
    local $SIG{__WARN__} = sub {
        my ($warning) = @_;

        # Replace some warnings:
        if($warning =~ /replaceme/) {
            print STDERR "My new warning.\n";
        }
        else {
            print STDERR $warning;
        }

        # Or do nothing to silence the warning.
    };

    carp "Wh00t!";
    carp "replaceme";
}

carp "Arrgh!";

Output:

Oh noes! at foo.pl line 8
Wh00t! at foo.pl line 25
My new warning.
Arrgh! at foo.pl line 29

In almost all cases you should prefer fixing the cause of the carp instead.

jkramer
My goal is not to silencing the carps but change a certain carp-warning in a die;
sid_com
I updated the example to demonstrate how to replace the output.
jkramer
Sorry, I think I got you wrong. Do you want to replace the warning text or do you want to die when a certain warning comes up?
jkramer
to die when a certain warning comes up.
sid_com
In that case, insert a die statement instead of the print the __WARN__ handler.
jkramer
+3  A: 

Based on your comments, my understanding is that you would like to make carp into a fatal warning.

If it is acceptable to make all carp warnings in your target package into fatal errors you can monkey-patch carp.

Carping Package:

package Foo;
use Carp;

sub annoying_sub {
    carp "Whine whine whine";
}

Main program:

use Foo;

*Foo::carp = \&Foo::croak;

Foo::annoying_sub();

If you want to limit the monkey patch to a dynamic scope, you can use local:

use Foo;

Foo::annoying_sub();  # non-fatal

{   local *Foo::carp = \&Foo::croak;
    Foo::annoying_sub();  # Fatal
}
daotoad
These are some of the techniques I talk about in _Mastering Perl_ for changing code without editing the original source :)
brian d foy
It looks like the line "local *Foo::carp = \" should be "local *Foo::carp = \" to get a die instead ot the warning ("Warning...Subroutine Number::Range::carp redefined at...").
sid_com

related questions