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

Hello,

I keep gettin this error!! and its sooooooooo annoying that I'm about to take off warnings!

view_quote.pl: Use of uninitialized value in string ne at C:\scripts\v +iew_quote.pl line 147.
What Can I do to make it go away??

I'm using a module, Finance::Yahooquote that retrieves certain fields, one of them being the # of Float shares which can be 333,000,000 or 222,000,223,222. Either in the millions or the billions. The module stores this field using three or four array items.

My code looks like this:
use Finance::YahooQuote; my @quotes = getcustomquote(["$symbol"], # using custom format ["Float Shares"]); my $found=0; foreach (@quotes) { $found++; if ($found > 1) { print "Only one stock symbol to view allowed."; die; + } my $float; if (${$_}[1] ne "") { if (${$_}[4] ne "") { $float = "${$_}[1],${$_}[2],${$_}[3],${$ +_}[4]"; } else { $float = "${$_}[1],${$_}[2],${$_}[3]"; } } else { $float = "n/a"; } print "$symbol Float Shares: $float"; } unless ($found) { print "No quote info. for symbol: $symbol"; }
The error only pops up when the float shares falls in the million range. For example, if its only 200,000,000 --then the last array item ${$_}4 is undefined and it gives me that error!! The line 147 points to the line where it has:
if (${$_}[4] ne "") { $float = "${$_}[1],${$_}[2],${$_}[3],${$ +_}[4]"; }
What can I do to make this error go away? How can I pre-define ${$_}4 when I don't know the outcome of the number of the shares?

Thanks Monks!@

Replies are listed 'Best First'.
Re: A confusing Use of uninitialized value
by davido (Cardinal) on Jun 06, 2005 at 04:04 UTC

    I'd first try to figure out why $_->[4] is undefined, or if it is, don't try testing its value or interpolating it into a string. But this should prevent the test that causes the warning without resorting to disabling warnings:

    if( defined $_->[4] and $_->[4] ne "" ) { $float = join ',', @{$_}[1..4]; }

    Note: The $_->[4] notation is functionally equivilant to, but IMHO easier to read than ${$_}[4]. I also happen to like using join on an array slice instead of typing out "${$_}[1],${$_}[2],${$_}[3],${$_}[4]", but that's not crucial to fixing your problem. The key is the defined test.


    Dave

Re: A confusing Use of uninitialized value
by brian_d_foy (Abbot) on Jun 06, 2005 at 04:27 UTC

    Is there something that's supposed to be in $_->[4] and it's missing, or it just doesn't have a value? That is, is there some bug besides the warning?

    In cases where I know I might get undef values, I cheat a bit. Rather than make the code that comes after it do all sorts of backflips to test the values, I just make sure they all have a value before I use them. Since undef turns into the empty string for stringy things, I replace those values with the empty string.

    my @array = map { defined $_ ? $_ : '' } @array[0..$last];

    Notice that I use an array slice on the right hand side. You don't need to do it that way, but you need to go through all of the elements you think you should have, including trailing undef (or missing) elements on the end.

    Alternately, you could pepper your code with a bunch of checks for defined(), but that can get in the way of whatever you are really trying to do.

    Other than that, I think you can get rid of a lot of code. It looks like you only want that first thing in @quotes, so you can just grab the first thing and ignore the rest. If there isn't anything there, you can die() right away (so you don't need $found), and the rest is just joining the elements. You could use this basic (and untested) structure:

    use Finance::YahooQuote; # only use the first anon. array returned my( $quote ) = getcustomquote([ $symbol ], ["Float Shares"]); # stop if we didn't get back something die "No quote info. for symbol: $symbol" unless ref $quote; my $float = $quote->[1] ne "" ? join( ",", @$quote ) : "n/a"; print "$symbol Float Shares: $float";

    Good luck :)

    --
    brian d foy <brian@stonehenge.com>
Re: A confusing Use of uninitialized value
by Zaxo (Archbishop) on Jun 06, 2005 at 04:01 UTC

    The $#array notation is handy when you don't know how big an array is. It is the last index in the array.

    my $float = $_->[1] ? join( ',', @{$_}[1..$#$_]) : 'n/a';
    You may want those indexes to run through 0..$#$_.

    After Compline,
    Zaxo