Search code examples
perl

How to make numeric warning fatal?


I am not able to make the numeric warning fatal:

use feature qw(say);
use strict;
use warnings;

my  $y = "a";
if ($y > 0) {
    say "Should not happen";
}
say "P1";
{
    say "y = $y";
    use warnings FATAL => qw(numeric);
    if ($y > 0) {
        say "Should not happen";
    }
}
say "Done";

Output is:

Argument "a" isn't numeric in numeric gt (>) at p.pl line 6.
P1
y = a
Done

Expected output:

Argument "a" isn't numeric in numeric gt (>) at p.pl line 6.
P1
y = a
Argument "a" isn't numeric in numeric gt (>) at p.pl line 13.

What am I missing?


Solution

  • Once you convert a variable to numeric, that conversion is cached. This means that $y is numeric after the first $y > 0, so the second neither warns nor dies.

    Modified test:

    use feature qw(say);
    use strict;
    use warnings;
    
    my  $y = my $z = "a";
    if ($y > 0) {
        say "Should not happen";
    }
    say "P1";
    {
        use warnings FATAL => qw(numeric);
        if ($z > 0) {
            say "Should not happen";
        }
    }
    say "Done";
    

    Output:

    Argument "a" isn't numeric in numeric gt (>) at a.pl line 6.
    P1
    Argument "a" isn't numeric in numeric gt (>) at a.pl line 12.
    

    We can see this caching with Devel::Peek. pIOK indicates an integer value is contained. (It's found in the IV slot.) pNOK indicates a floating point value is contained. (It's found in the NV slot.)

    $ perl -MDevel::Peek -we'my $y = "a"; Dump( $y ); 0+$y; Dump( $y );'
    SV = PV(0x56336a2a3ea0) at 0x56336a2d2d00
      REFCNT = 1
      FLAGS = (POK,IsCOW,pPOK)
      PV = 0x56336a2db600 "a"\0
      CUR = 1
      LEN = 10
      COW_REFCNT = 1
    Argument "a" isn't numeric in addition (+) at -e line 1.
    SV = PVNV(0x56336a2a2220) at 0x56336a2d2d00
      REFCNT = 1
      FLAGS = (POK,IsCOW,pIOK,pNOK,pPOK)
      IV = 0
      NV = 0
      PV = 0x56336a2db600 "a"\0
      CUR = 1
      LEN = 10
      COW_REFCNT = 1