Stefan Majewsky
Stefan Majewsky

Reputation: 5555

Can I "use warnings" only in one subroutine?

I’m working on a Perl CGI script about 4000 lines big. Our coding style includes use strict and use warnings usually, but in this particular (quite old) file, "use warnings" is commented out, with the comment stating that enabling warnings would flood the Apache log.

Now I plan to separate some code into a new subroutine. I want to use warnings at least there. How can I safely limit the effect of use warnings to one subroutine? Will just placing the use clause inside the subroutine do the job?

Upvotes: 4

Views: 281

Answers (6)

TLP
TLP

Reputation: 67900

The answer that use warnings can be used lexically is correct. The solution to use no warnings lexically and use warnings globally is more correct. The correctest solution is to fix all your warnings. Somewhere in between lies redirecting the errors.

use warnings;
open STDERR, ">>", "foo/error.log" or die $!;

Leave that up for a while, then run:

perl -nlwe '$a{$_}++ }{ print for keys %a' foo/error.log > foo/errors.dedupe

Go through the code and fix the warnings. Most likely, if the script is working, they will be trivial. But unless you check, how do you know?

If in the end you decide that its not worth the hassle to fix all the warnings, then just remove the warnings and error redirection and use warnings lexically.

Upvotes: 2

Filip Roséen
Filip Roséen

Reputation: 63797

Yes, the use of use warning will be in the scope in which you have written it.

Writing use warning inside a sub will only affect the giving routine (or block).


example snippet

sub foo {
  use warnings;
  print  my $a; 
}

{
  use warnings;
  print  my $b;
}

foo;

print my $c;

output

Use of uninitialized value $b in print at foo.pl line 8.
Use of uninitialized value $a in print at foo.pl line 3.

Note that no warning is thrown about the use of print my $c.


What does the documentation say?

  • perldoc.perllexwarn

    This pragma works just like the strict pragma. This means that the scope of the warning pragma is limited to the enclosing block. It also means that the pragma setting will not leak across files (via use, require or do). This allows authors to independently define the degree of warning checks that will be applied to their module.

Upvotes: 13

zgpmax
zgpmax

Reputation: 2847

Turning on warnings globally, then turning it off for specific sections sounds like a good plan.

You don't have to put use warnings; or no warnings; inside every sub. You can make ad-hoc scopes using braces, eg.

use warnings;

sub nice_new_sub_1 { ... }

sub nice_new_sub_2 { ... }

{
    no warnings;

    sub nasty_old_sub_3 { ... }

    sub nasty_old_sub_4 { ... }

    sub nasty_old_sub_5 { ... }
}

Also, consider turning off only those warnings you need to make it work cleanly, e.g.

{
    no strict 'refs';

    sub nasty_old_sub_3 { ... }

    sub nasty_old_sub_4 { ... }
}

Upvotes: 2

Dave Cross
Dave Cross

Reputation: 69244

Yes, as other people have pointed out. But, in my opinion, you would be better advised to turn on warnings globally and just turn them off around problematic sections of code.

use warnings;

sub new_method {
  # shiny new code
}

sub old_method {
  no warnings;

  # nasty old code
}

Upvotes: 4

Ilion
Ilion

Reputation: 6872

Yes. From the perldoc:

The warnings pragma is a replacement for the command line flag -w , but the pragma is limited to the enclosing block, while the flag is global.

http://perldoc.perl.org/warnings.html

Upvotes: 3

Stefan Majewsky
Stefan Majewsky

Reputation: 5555

Just found the answer myself in "perldoc perllexwarn":

...the scope of the warning pragma is limited to the enclosing block.

So the following should work:

sub new_method {
    use warnings;
    ...
}

sub old_method {
    ... # no warnings here
}

Upvotes: 2

Related Questions