Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Annoying 'Use of uninitialized value in concatenation' warning

by alain_desilets (Beadle)
on Oct 25, 2011 at 19:47 UTC ( [id://933686]=perlquestion: print w/replies, xml ) Need Help??

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

Hi folks,

I have been using 'use strict' for years, but was only recently introduced to 'use warnings'. While I find it generally useful, it tends to generate warnings in contexts where I think it shouldn't, in particular when trying to print a variable whose value is undef.

For example, consider the following code:

use strict; use warnings; my @some_array = (1, 2, undef, 4, 5); for (my $ii=0; $ii < scalar(@some_array); $ii++) { print "Value at position $ii: $some_array[$ii]\n"; }

This code prints the elements of an array, some of which have value undef. If you run it, you get error messages

"Use of uninitialized value $some_array2 in concatenation (.) or string at etc..."

Yet, it's perfectly fine for an array to contain some values of undef. Why shouldn't I be allowed to print them?

Is there a way around this issue? Thx.

Replies are listed 'Best First'.
Re: Annoying 'Use of uninitialized value in concatenation' warning
by runrig (Abbot) on Oct 25, 2011 at 19:55 UTC
    If you don't care about uninitialized warnings in your loop then put in your loop:
    no warnings 'uninitialized';

    If you don't care about uninitialized warnings in the entire script, then put that line right underneath the use warnings line.

    If you don't care about any sort of warnings at all, then don't include a use warnings line.

Re: Annoying 'Use of uninitialized value in concatenation' warning
by BrowserUk (Patriarch) on Oct 25, 2011 at 20:09 UTC
    Yet, it's perfectly fine for an array to contain some values of undef. Why shouldn't I be allowed to print them?

    Because you cannot "print undef"!

    Without the warning, there is no way to distinguish between print ''; and print undef;.

    Which may be fine in some contexts, but can be strongly indicative of a serious error in others.

    Hence the warning is optional and turn on and off able. You can choose to turn it off in individual blocks of code, or if you feel it never benefits you, turn it off at the top of the module: use warnings; no warnings 'uninitialized';

    It's a shame there isn't a better syntax for enabling everything except one or two categories.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I agree with BrowserUk, I think it's important to know when you are trying to use an initialized variable. Good to know that you can turn it off when needed. Your other option is to used empty strings instead of undef.

      I also agree ... completely.

      “Warnings are your friends,” because the only party that can realistically tell you what a computer program is doing wrong is ... the computer itself.   Nevertheless you may decide that there are specific places in your program where an innocuous condition such as this one is causing a boatload of unwanted error-messages, e.g. in an Apache error log, and therefore you justifiably want to stamp the message out because it’s doing more harm than good.   In those cases, Perl does allow you to do that.   And, as BrowserUK wisely suggests, when you elect to do such a thing, you ought to do so in a very targeted way.   Suppress only the specific warnings you need to suppress, and do so only within a limited section of the code.   (I further advise that you add detailed comments surrounding the area:   “exactly what are you intending to suppress, and exactly why.”   Copying a representative handful of the actual message-texts and pasting them right into the comment-block is a pretty good idea to me, ’cuz you will forget these things.)

      Fav’d.

Re: Annoying 'Use of uninitialized value in concatenation' warning
by Perlbotics (Archbishop) on Oct 25, 2011 at 20:06 UTC

    You can silence the warning (if you know what you do) or you can detect and treat the undef-case. However, it is wise to keep the no warnings; scope small. Update: See also johngg's hint below about the do{ ... } trick.

    When in doubt, I suggest to treat the undef-case, and let the warning pragma do its job. Often, an undef warning reveals a bug that was otherwise undetected.

    use strict; use warnings; sub original_post { my @some_array = (1, 2, undef, 4, 5); for (my $ii=0; $ii < scalar(@some_array); $ii++) { print "Value at position $ii: $some_array[$ii]\n"; } } sub detect_undef_and_set { my @some_array = (1, 2, undef, 4, 5); #alternative-1: fix data structure # @some_array = map { $_ // '(oops! undef!!)' } @some_array; for (my $ii=0; $ii < scalar(@some_array); $ii++) { #alternative-2: fix output print "Value at position $ii: ", $some_array[$ii] // '(oops! undef +!)' , "\n"; } } sub no_warnings { my @some_array = (1, 2, undef, 4, 5); for (my $ii=0; $ii < scalar(@some_array); $ii++) { no warnings 'uninitialized'; # for this lex scope only print "Value at position $ii: $some_array[$ii]\n"; } } print "ORIG:\n"; original_post(); print "CHECK:\n"; detect_undef_and_set(); print "NO WARN:\n"; no_warnings(); __DATA__ RIG: Value at position 0: 1 Value at position 1: 2 Use of uninitialized value $some_array[2] in concatenation (.) or stri +ng at nowarn.pl line 7. Value at position 2: Value at position 3: 4 Value at position 4: 5 CHECK: Value at position 0: 1 Value at position 1: 2 Value at position 2: (oops! undef!) Value at position 3: 4 Value at position 4: 5 NO WARN: Value at position 0: 1 Value at position 1: 2 Value at position 2: Value at position 3: 4 Value at position 4: 5

      You can confine the no warnings 'uninitialised'; to the lexical scope but you can make it even tighter if you wish by confining it to the print with the use of a do block.

      for (my $ii=0; $ii < scalar(@some_array); $ii++) { print do { no warnings 'uninitialized'; # for the do block only "Value at position $ii: $some_array[$ii]\n"; }; }

      I hope this is of interest.

      Cheers,

      JohnGG

Re: Annoying 'Use of uninitialized value in concatenation' warning
by toolic (Bishop) on Oct 25, 2011 at 20:09 UTC
    ... furthermore, controlling this behavior is described in the documentation available at your fingertips:

    perldoc warnings

    which also points to perllexwarn

      Thx. I was already familiar with the "no warning 'xyz'", but I hadn't found the names of all the warning categories. Alain
Re: Annoying 'Use of uninitialized value in concatenation' warning
by GrandFather (Saint) on Oct 26, 2011 at 01:40 UTC

    If you want to make the undef value obvious in the output then you could:

    use warnings; use strict; use 5.010; my @some_array = (1, 2, undef, 4, 5); for (my $ii = 0; $ii < scalar(@some_array); $ii++) { print "Value at position $ii: @{[$some_array[$ii] // '--undef--']} +\n"; }

    Prints:

    Value at position 0: 1 Value at position 1: 2 Value at position 2: --undef-- Value at position 3: 4 Value at position 4: 5
    True laziness is hard work
      another option without concatenation:
      print "Value at position $ii: ", $some_array[$ii] || '--undef--',"\n";

        The problem with using the  || (logical-or) operator (see perlop) in this case is that the undefined value is false, as are 0, '0' and '' (the empty string), and  || does not distinguish. If your Perl version is 5.10+, you can use the  // (defined-or) operator; otherwise, you're stuck with syntax that's a bit more messy:

        c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; my @ra = (0, 0, 0); ;; my $i = 1; print qq{value at index $i: }, $ra[$i] || 'undef'; print qq{value at index $i: }, $ra[$i] // 'undef'; print qq{value at index $i: }, defined($ra[$i]) ? $ra[$i] : 'undef' " value at index 1: undef value at index 1: 0 value at index 1: 0


        Give a man a fish:  <%-(-(-(-<

Re: Annoying 'Use of uninitialized value in concatenation' warning
by mbethke (Hermit) on Oct 25, 2011 at 20:47 UTC

    What runrig said.

    The reason for having a warning about this is that while undef is a perfectly valid value for a variable, it has no textual representation. Printing it will render it as an empty string but Perl will warn you that what you're seeing may not be what you wanted. More often than not, having undefs printed indicates that you forgot to calculate/read/whatever some value.

      The reason for having a warning about this is that while undef is a perfectly valid value for a variable, it has no textual representation.
      Bullshit.

      There are also characters that have no textual representation, and using them doesn't warn.

      Note that the warning from the OP isn't even about printing - it's about concatenation. There's a perfectly good reason why most operations warn if one of its operands is undefined, but having no textual representation isn't that reason.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://933686]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-19 07:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found