[Chicago-talk] Use of uninitialized value in printf

Alan Mead amead at alanmead.org
Wed Aug 19 14:36:12 PDT 2020


I'm trying to use Statistics::Basic to calculate basic statistics like
correlations. These functions return objects which are supposed to
magically become numbers as needed, 
https://metacpan.org/pod/distribution/Statistics-Basic/lib/Statistics/Basic.pod:
> These actually return objects, not numbers. The objects will
> interpolate as nicely formated numbers (using Number::Format). Or the
> actual number will be returned when the object is used as a number.

But I have a situation where the magic fails. When one (or both) vector
has no variance, the correlation should be zero but the value of the
object is neither defined, nor undefined, it's uninitialized.

The code is below, here's the output that's driving me crazy. The 0.00
is correct, but the warnings are annoying:

$ ./corr.pl
1,0.426
Use of uninitialized value in printf at ./corr.pl line 20.
2,0.000
Use of uninitialized value in addition (+) at ./corr.pl line 25.
3,0.000

Surely there's a way to force an object to be reduced into a scalar
float (as opposed to just hiding the warnings)?

I've tried the following:

  * using scalar() (does nothing);
  * adding 0 and 0.0 (just moves where the same error is reported);
  * dereferencing the object and trying to force a scalar with scalar
    references: "${ $corr }" and "${ $correlation( \@v1, \@v2 ) }"
    (these are all: Not a SCALAR reference);
  * checking if $corr is defined (it is, it's a defined object); and
  * adding ' || 0' to the end of the definition (does nothing).

I can solve the issue with this:

$corr = ( defined correlation( \@v1, \@v2 ) ? correlation( \@v1, \@v2 )
: 0 );

but then I'm forced to compute the correlation twice, which seems like a
pretty poor solution.

You might argue that corr = cov / ( sd1 sd2 ) and therefore that corr is
undefined when sd1 or sd2 are zero, but in this case cov = 0 (by
definition) and it's really unhelpful to me for this function to return
an non-value, particularly because this issue would only arise
occasionally leading to potentially difficult bugs.

What I need is a way to force the object to collapse into a scalar value
and assign that value to a variable. Any thoughts?

-Alan


#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;
use Statistics::Basic qw(:all);

my @v1 = ( 1, 2, 2, 3 );
my @v2 = ( 1, 0, 2, 2 );

# good data; everything's ok
my $corr = correlation( \@v1, \@v2 );
printf "%d,%.3f\n", 1, $corr;

# correlation is zero because v2 has no variance
# Use of uninitialized value in printf at ./corr.pl line 20.
@v2 = ( 1, 1, 1, 1 );
$corr = correlation( \@v1, \@v2 );
printf "%d,%.3f\n", 2, $corr;
#print Dumper( $corr ), "\n";

# v2 still has no variance
# Use of uninitialized value in addition (+) at ./corr.pl line 25.
$corr = 0 + scalar( correlation( \@v1, \@v2 ) );
printf "%d,%.3f\n", 3, $corr;
#print Dumper( $corr ), "\n";

-- 

Alan D. Mead, Ph.D.
President, Talent Algorithms Inc.

science + technology = better workers

http://www.alanmead.org


Acton's dictate: Power tends to corrupt, and absolute power corrupts
absolutely. Great men are almost always bad men, even when they exercise
influence and not authority.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/chicago-talk/attachments/20200819/fbbb418b/attachment.html>


More information about the Chicago-talk mailing list