Plankton has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I do not like getting warnings in my code but I like to use !~ to remove patterns of text from strings, you know ...

$str !~ s/junk//g;
... but this generates ...
Useless use of not in void context at ...
... messages because I like to "-w". I can suppress these warning messages by doing this ...
if ( $str !~ s/junk//g ) {}
... but that might be a little confusing to someone that might end up maintaining my code (me :p ). Is there a more readable way to suppress the void context warnings?

Thanks

  • Comment on Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
by ikegami (Patriarch) on Jan 25, 2009 at 05:55 UTC

    Just to elaborate on what the others have said,

    $str !~ s/junk//g;

    means

    !( $str =~ s/junk//g );

    In fact, both generate exactly the same opcode tree. You'd expect the latter to warn in void context, right? Well, so does the former. So just drop the negation.

    $str =~ s/junk//g;
Re: Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
by Your Mother (Archbishop) on Jan 25, 2009 at 05:28 UTC

    That construct is tres-weird. I didn't even know it would work. Learn something new. :) I'd say, just use =~ like Dog intended.

    perl -wle '$str = "not junk"; $str !~ s/junk//g; print $str' Useless use of not in void context at -e line 1. not perl -wle '$str = "not junk"; $str =~ s/junk//g; print $str' not
    Update: the warning in 5.10 is a bit more informative than the one in 5.8 too: "Useless use of negative pattern binding (!~) in void context at -e line 1."
      Oh yeah ... I got in my head some how that one should use !~ to "remove" or "negate" patterns and =~ to "match" or "find equivalent" patterns. Thanks for clearing away the bad burn in.
Re: Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
by GrandFather (Saint) on Jan 25, 2009 at 05:46 UTC

    The not match operator !~ is not appropriate in the context of a substitution so the Perl interpreter gets confused (so will anyone else reading your code). In what fashion do you expect !~ to behave differently than =~ (what you should be using) in the context of substitution?


    Perl's payment curve coincides with its learning curve.
Re: Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
by ysth (Canon) on Jan 25, 2009 at 10:00 UTC
    You should use =~, not !~.

    But in general, you can get rid of "Useless use of...in void context" by giving a non-void context. The easiest way to do this is

    scalar( $str !~ s/junk//g );
    In 5.6.0 and earlier, this didn't work, but I think this did:
    1 if $str !~ s/junk//g;
    (The constants 0 and 1 are exempt from the "Useless use" warning.)
Re: Is there a better way of dealing with !~ and "Useless use of not in void context at" warnings?
by davido (Cardinal) on Jan 25, 2009 at 06:12 UTC

    Warnings can be lexically scoped. Hence:

    use strict; use warnings; my $str = "junk not junk"; { no warnings qw/void/; $str !~ s/junk//g; }

    This silences the "void context" warning but only on operations that occur within the curly brackets. perllexwarn for more fun details.

    I prefer this method to your if(){} method, because it is easier to understand if you come along six months down the road and wonder why on earth you wrapped a substitution in an empty if(){} statement. Looking at the no warnings code, you'll remember, "Oh, I'm squelching a void context warning." The if(){} method, you'll look and say to yourself, "What was I thinking?" My way utilizes the primary purpose of the "no warnings" construct. You were well justified in looking for a better way as the method you suggested utilizes a tertiary side-effect of the if(){} statement.

    Great question, by the way.


    Dave