Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Uninitialized value in string warnings (was: Warnings:)

by Anonymous Monk
on Jun 08, 2002 at 01:06 UTC ( [id://172712]=perlquestion: print w/replies, xml ) Need Help??

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

Is there an easy way to lookup the causes and possible solutions to the use warnings messages?

The particular one I am getting is: warning: Use of uninitialized value in string at line 14.

14:my $c = "$a$b";

At this point, $b may or may not contain anything - if its does, it want it if not that's ok too.

I tried my c$ = "$a$b" if ($b); but that means c$ doesn't get defined if b$ has no value. So then I have to move to my c$ = ($b) ? "$a$b" : "$a"; but that seems a bit hookey to prevent a warning about something I knew would be true and didn't mind?

Is there a better way of avoding the warning?

Edit kudra, 2002-06-08 Changed title

Replies are listed 'Best First'.
Re: Warnings:
by Zaxo (Archbishop) on Jun 08, 2002 at 01:22 UTC

    Changing $a and $b to $u and $v. See perlvar for why.

    $u ||= ''; $v ||= ''; my $c = $u . $v;
    The quotes are unnecessary, concatenation is enough.

    You can look up perl's trouble messages in perldiag, which you will have (in the most relevant edition) on your local perl box.

    Update: A word of explanation and a caveat. The '||=' operator tests for truth and assigns if false. That makes mine fail if $u or $v is zero. vagnerr's ternary on defined() does not suffer from this flaw.

    Update 2 AM: $a and $b are package global variables internally defined in perl. They act as temporaries within sort to hold the two values currently being compared. It is dangerous to tread on those. Good news for you, $foo ||= 'bar' is an expression which returns $foo's final value, so the code above could be written as:

    my $c = ($u ||= '') . ($v ||= '');
    or even:
    my $c = (defined $u ? $u : '') . (defined $v ? $v : '');
    The second does not modify $u and $v, and is well behaved for zero terms.

    Concerning program design: it's a good idea to have a definite place where a variable is always given a defined value. That places the burden on one statement, and lets other sections of code forget about these problems. Just another form of loose coupling.

    After Compline,

      I re-read the perlvar stuff, but I still don't understand the significance of the change from $a/b to $u/v?

      The code given is only an example, the real code uses descriptive variable names and has other constant info around the two vars.

      I had found perldiag, but was hoping for a quick way of finding a particular message, something like the perldoc -q re that works for perlfaq?

      The My $c = "$a$b" is a gross simplification of the real line. The problem is that the value of $b is set (or not) with the same compound statement. For me to ensure that it has a value requires me to break the compound statement into a loop in order to intercept and test the value of $b before using it, which I was hoping to avoid.

      However, I wasn't aware of the ||= operator, it will be useful in other situations. Thanks.

      Ok, understand about the potential clash of $a$b with the sort module, though it seems like bad design that I can clash with system vars that use common names. A problem with all languages that opt for implicitly global vars rather than implicitly local.

      I still don't see how your reference to perlvar would help me? The only occurences of $a or $b that I could find in there are where they are used in an example!

      I thought and tried inserting the bracketed ternary expressions into the compound expression as you suggested, but have so far been spectacularly unsucessful in preventing them from generating more and worse errors than I am trying to cure.

      I realise that this is probably down to my inexperience rather than because it isn't a good thanks!

      Re: Program design: Good, sage advice which in most any other situation I would totally agree with. Trouble in this case is that the variable ($b) in the original example, is actually generated within the compound statement and comes into existance and disappears automagically. I have successfully unwound the statement into a loop which allows me to preinitialise $b at an appropriate block level, but (so far) the syntatic salt needed to make it work within the compound statement eludes me. And as the unwound (looping) statement appears to be considerably less efficient that the compound one, disabling this individual warning for a block encompassing this one statement seems the appropriate way to go.

Re: Warnings:
by samtregar (Abbot) on Jun 08, 2002 at 01:31 UTC
    Try "use diagnostics" to see a helpful message from perldiag with every warning.


Re: Warnings:
by vagnerr (Prior) on Jun 08, 2002 at 01:31 UTC
    You could try using diagnostics:-
    just add the following to your program
    use diagnostics;
    you may need to comment out use strict; and remove the '-w' flag. What diagnostics does is give you a discription of what may be the problem.

    In you particular case you are faced with using a possibly undefined variable as you have stated. You could either go ahead with your proposed idea, or "initialise" everything at the start of your code. EG
    $a=""; $b=""; $c="";
    Or you could put your potentialy uninitialied variable into a safe state after it is defined and before use eg.
    $b = defined($b)?$b:"";

    Hope this helps.

    ---If it doesn't fit use a bigger hammer

      I'm already using:

      #!perl.exe -w use strict; use diagnostics;

      but I don't want to turn off warnings or strict for the whole program to avoid this which I know about and am ready to except.

      See above (or below?) for my reply to the previous poster for why I was trying to avoid the ternary op.


Re: Warnings:
by jsprat (Curate) on Jun 08, 2002 at 02:31 UTC
    1. initialize $b as many have said above, or
    2. if you know and don't care that the variable may be uninitialized, add no warnings 'uninitialized'; in the smallest possible scope.
    I will usually use the 'no warnings' pragma when looping through a DBI recordset, rather than try to initialize each variable prior to its use.

      Thanks. 2) Is exactly what I needed.

Re: Warnings:
by ariels (Curate) on Jun 08, 2002 at 08:12 UTC
    Apart from using diagnostics to print out longer error messages, you can also use the "program" version of diagnostics, called "splain". Just pipe your error messages to <samp>splain</samp>, or paste them into its standard input, or whatever.

    Here's how it works:

    #&91;ariels@HumptyDumpty ariels]$ splain 
    /usr/bin/splain: Reading from STDIN
    Use of uninitialized value in string at line 14.
    Use of uninitialized value in string at line 14 (#1)
        (W uninitialized) An undefined value was used as if it were already defined.  It was
        interpreted as a "" or a 0, but maybe it was a mistake.  To suppress this
        warning assign a defined value to your variables.

      Thanks. Splain is great! Saves much manual searching of the perldiag docs (which on Win32 system with the standard more is less than useful).

      Anyone have an existing perl script that improves on the standard Win32 more? <p.Shouldn't be hard to write in Perl to get something that goes backward as well as forwards and has a decent (or even primative!) search facility - but if anyone has one existing I'd be grateful.

Log In?

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-04-23 23:28 GMT
Find Nodes?
    Voting Booth?

    No recent polls found