Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > warnings dilemma

Reply
Thread Tools

warnings dilemma

 
 
kj
Guest
Posts: n/a
 
      05-10-2007


I've read the PODs (warnings, perllexwarn) but I still don't know
how to solve this problem. Here's a toy version of it.

First some random module:

# Foo.pm
package Foo;
use strict;
use warnings;

# calling foo() will result in an 'uninitialized' warning
sub foo { my %h; exists $h{ $_[ 0 ] } }
1;

__END__



The function Foo::foo represents one of those situtations in which
the author of the module, for whatever reason, has not taken steps
to avoid a default warning.

Next, my script

use strict;
use Foo;
{ no warnings; Foo::foo(); }
exit;


Now, despite the "no warnings" in the script, when I run it I still
get the "Use of initialized value in exists" warning.

I know that I can silence the warnings by setting $SIG{__WARN__}
in the script to a suitable handler, but this leads to parsing the
text of warning messages, which is an invitation for bugs, and
basically throws the nice warnings pragma warnings hierarchy out
the window. (If there's a way to define $SIG{__WARN__} to mimic
the effects of "no warnings 'foobar'" without having to parse
warning messages in order to *guess* whether a particular warning
belongs to the "foobar" category, please let me know.)

Of course, I could remove "use warnings" from Foo.pm (or pester
its author to do so), then the warnings would *never* show up even
if the script were changed to

use strict;
use Foo;
{ use warnings; Foo::foo(); }
exit;

This is not good. Why? Because module authors are fallible like
everyone else, and despite their best efforts, a situation warranting
a warning will slip through, so it is nice to make those warnings
visible. I.e. putting "use warnings" at the top of each module
file seems to me like a fine idea. Except that then the script
*can't* turn off warnings!

I am at a loss. It seems that either alternative (including "use
warnings" in Foo.pm or leaving it out) leads to an undesirable
behavior.

IMO, the calling executable should have the final say on which
warnings get emitted. Is there a way to do this without having to
resort to defining $SIG{__WARN__} and parsing warning messages?

Thanks!

kj

--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.
 
Reply With Quote
 
 
 
 
Brian McCauley
Guest
Posts: n/a
 
      05-10-2007
On May 10, 5:28 pm, kj <(E-Mail Removed)> wrote:
> I've read the PODs (warnings, perllexwarn) but I still don't know
> how to solve this problem. Here's a toy version of it.
>
> First some random module:
>
> # Foo.pm
> package Foo;
> use strict;
> use warnings;
>
> # calling foo() will result in an 'uninitialized' warning
> sub foo { my %h; exists $h{ $_[ 0 ] } }
> 1;
>
> __END__
>
> The function Foo::foo represents one of those situtations in which
> the author of the module, for whatever reason, has not taken steps
> to avoid a default warning.


So you don't like something about the way the module works. Why is
this any different from anything else about the way the module works?

> Next, my script
>
> use strict;
> use Foo;
> { no warnings; Foo::foo(); }
> exit;
>
> Now, despite the "no warnings" in the script, when I run it I still
> get the "Use of initialized value in exists" warning.


That's right. That's the whole point of lexical scope. You can choose
one warning level in your script and the author of the module can
choose another without the two interacting.

> I know that I can silence the warnings by setting $SIG{__WARN__}
> in the script to a suitable handler, but this leads to parsing the
> text of warning messages, which is an invitation for bugs, and
> basically throws the nice warnings pragma warnings hierarchy out
> the window.


But if you objective is to break down the nice isolation that is
provided by lexically scoped warning control and want to fiddle with
warnings from another lexical scope then that's what you're stuck with
(AFAIK).

> (If there's a way to define $SIG{__WARN__} to mimic
> the effects of "no warnings 'foobar'" without having to parse
> warning messages in order to *guess* whether a particular warning
> belongs to the "foobar" category, please let me know.)


No the messages that passed to the $SIG{__WARN__} are just plain
strings they don't AFAIK have hidden information about the warning's
position in the hierarchy.

Anyhow I don't get it - I thought you wanted to filter out warning
that came from the module Foo, not warnings of a particular category.

> Of course, I could remove "use warnings" from Foo.pm (or pester
> its author to do so), then the warnings would *never* show up even
> if the script were changed to
>
> use strict;
> use Foo;
> { use warnings; Foo::foo(); }
> exit;
>
> This is not good. Why? Because module authors are fallible like
> everyone else, and despite their best efforts, a situation warranting
> a warning will slip through, so it is nice to make those warnings
> visible. I.e. putting "use warnings" at the top of each module
> file seems to me like a fine idea. Except that then the script
> *can't* turn off warnings!


Bugs in the module show up in the module. They are fixed by fixing the
module. Why is this a problem?

> I am at a loss. It seems that either alternative (including "use
> warnings" in Foo.pm or leaving it out) leads to an undesirable
> behavior.


You could, of course, edit the module do the right thing.

sub foo { my %h; no warnings 'uninitialized'; exists $h{ $_[ 0 ] } }

This gets rid of the warning and serves as a comment that the author
is intentionally treating undef as '' in the remainder of the block.

> IMO, the calling executable should have the final say on which
> warnings get emitted.


That's why $SIG{__WARN__} is still useful.

> Is there a way to do this without having to
> resort to defining $SIG{__WARN__} and parsing warning messages?


Well the alternative is to redirect STDERR.

{
local *STDERR;
open STDERR, '>', '/dev/null'; # IIRC /dev/null is special-cased
Foo::foo();
}

Note this won't stop warnings that are sent directly to FD2 by
subprocesses or non-Perl libraries. To intercept those see (my
contributions to) numerous previous threads on the subject of
capturing STDERR.

 
Reply With Quote
 
 
 
 
kj
Guest
Posts: n/a
 
      05-10-2007
In <(E-Mail Removed) om> Brian McCauley <(E-Mail Removed)> writes:

>On May 10, 5:28 pm, kj <(E-Mail Removed)> wrote:
>> I've read the PODs (warnings, perllexwarn) but I still don't know
>> how to solve this problem. Here's a toy version of it.
>>
>> First some random module:
>>
>> # Foo.pm
>> package Foo;
>> use strict;
>> use warnings;
>>
>> # calling foo() will result in an 'uninitialized' warning
>> sub foo { my %h; exists $h{ $_[ 0 ] } }
>> 1;
>>
>> __END__
>>
>> The function Foo::foo represents one of those situtations in which
>> the author of the module, for whatever reason, has not taken steps
>> to avoid a default warning.


>So you don't like something about the way the module works.


No, that's *not* the problem. The problem is that, as far as I
can tell, there is no good way (either through code or through
coding practices) to provide control over warnings to the calling
script. Every alternative is deficient in one way or another.

>> Next, my script
>>
>> use strict;
>> use Foo;
>> { no warnings; Foo::foo(); }
>> exit;
>>
>> Now, despite the "no warnings" in the script, when I run it I still
>> get the "Use of initialized value in exists" warning.


>That's right. That's the whole point of lexical scope.


I disagree. I think a far more useful implementation of lexical
control is to give each lexical scope the ability to control which
warnings it allows to "bubble up" through it, in a way entirely
analogous to the lexical control of fatal errors with eval. E.g.
under this version, code like this:

if ( $verbose ) {
use warnings;
Foo::foo();
}
else {
no warnings;
Foo::foo();
}

would result in warnings only if $verbose is true. This is more
useful than what we have now, because it privileges scopes in
proportion to their proximity to the top-level scope, as it should
be. I don't understand why it wasn't designed like this in the
first place...

kj
--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-11-2007
On 10 May, 22:05, kj <(E-Mail Removed)> wrote:
> In <(E-Mail Removed) om> Brian McCauley <(E-Mail Removed)> writes:
>
>
>
> >On May 10, 5:28 pm, kj <(E-Mail Removed)> wrote:
> >> I've read the PODs (warnings, perllexwarn) but I still don't know
> >> how to solve this problem. Here's a toy version of it.

>
> >> First some random module:

>
> >> # Foo.pm
> >> package Foo;
> >> use strict;
> >> use warnings;

>
> >> # calling foo() will result in an 'uninitialized' warning
> >> sub foo { my %h; exists $h{ $_[ 0 ] } }
> >> 1;

>
> >> __END__

>
> >> The function Foo::foo represents one of those situtations in which
> >> the author of the module, for whatever reason, has not taken steps
> >> to avoid a default warning.

> >So you don't like something about the way the module works.

>
> No, that's *not* the problem. The problem is that, as far as I
> can tell, there is no good way (either through code or through
> coding practices) to provide control over warnings to the calling
> script. Every alternative is deficient in one way or another.


Well, yes that's true. Nothing's perfect.

> >> Next, my script

>
> >> use strict;
> >> use Foo;
> >> { no warnings; Foo::foo(); }
> >> exit;

>
> >> Now, despite the "no warnings" in the script, when I run it I still
> >> get the "Use of initialized value in exists" warning.

> >That's right. That's the whole point of lexical scope.

>
> I disagree. I think a far more useful implementation of lexical
> control is to give each lexical scope the ability to control which
> warnings it allows to "bubble up" through it, in a way entirely
> analogous to the lexical control of fatal errors with eval.


The scope of control of fatal errors with eval() is _not_ lexical.
"Lexically scoped" describes the way "use warnings" or "use strict"
works now. What you want is the opposite of lexical scope - "dynamic
scope". This is what we had before we had lexical control with
local($^W) and what we still have with local($SIG{__WARN__}).

> E.g.
> under this version, code like this:
>
> if ( $verbose ) {
> use warnings;
> Foo::foo();
> }
> else {
> no warnings;
> Foo::foo();
> }
>
> would result in warnings only if $verbose is true. This is more
> useful than what we have now,


No it isn't. I'm not saying that the functionality you want would not
be useful sometimes but it would be usefull less often than what we
have now. I want to be able to suppress or promote warnings
selectively in _my_ code without an action-at-a-distance on other code
I happen to be calling.

> because it privileges scopes in
> proportion to their proximity to the top-level scope, as it should
> be.


I disagree. The descision as to which warning-causing circumstances
are expected and which are not (and which should be errors) belongs as
close as possible to where the expectation applies.

> I don't understand why it wasn't designed like this in the
> first place...


Because the designers agree with my way of thinking.

With perl 5.10's new caller() you could write a lexically scoped
pragma that actually had dynamically scoped effect because you have
access to all the lexical scope hints in all calling stack frames.
However the bit that's responsible for determining what warning
categories are enabled is not AFAIK replacable so you couldn't make
this selective by category. As I said before that probably doesn't
matter because for what you are trying to do filtering by category
does not make much sense anyhow.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
OT: Dilemma CBIC MCSE 23 08-29-2005 03:21 PM
Wireless Printing Dilemma =?Utf-8?B?YmhpZ2dpbnM=?= Wireless Networking 3 01-10-2005 03:39 PM
Router / Wireless Router Dilemma RedRover Wireless Networking 2 12-16-2004 06:21 PM
use warnings; and use Warnings; give different results Ted Sung Perl Misc 1 08-30-2004 10:22 PM
Set focus on a form control dilemma Chris ASP .Net 0 11-10-2003 10:19 AM



Advertisments