Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Can't use an undefined value as an ARRAY reference at ./test.pl line 14.

by Anonymous Monk
on Oct 28, 2016 at 03:27 UTC ( [id://1174869]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
I have a small code like below. I saved this into a file named as: ./test.pl

If we run this code without using the option -libFile like this:
test.pl -test true
it writes out the message:
Can't use an undefined value as an ARRAY reference at ./test.pl line 14.

How should I initialize $lib on Line 7? I tried setting it to an empty array but it did not help. Kindly help!
Robert
1 #!/usr/bin/perl 2 use strict; 3 use warnings; 4 5 use Getopt::Long; 6 my $test = "true"; 7 my $lib ; 8 9 GetOptions("libFile=s@" => \$lib, 10 "test=s" => \$test, 11 ); 12 13 if($test eq "true") { 14 if( (scalar @$lib) > 0) { 15 print "Pass\n"; 16 } 17 }

Replies are listed 'Best First'.
Re: Can't use an undefined value as an ARRAY reference at ./test.pl line 14.
by davido (Cardinal) on Oct 28, 2016 at 05:57 UTC

    First of all, congratulations for the good sense to use strict and warnings.

    Let's walk through your script's run:

    1. $test is declared and defined with the string of true.
    2. $lib is declared but not defined (meaning, no value is assigned to initialize it. When a variable is not defined, in Perl, loosely speaking, it contains undef.
    3. GetOptions is invoked, and detects that the test flag appeared on the command line with a value of "true". The libFile flag was NOT provided on the command line, so no value is assigned to $lib
    4. The first conditional detects that $test contains true, so we move into the second conditional.
    5. The second conditional attempts to dereference $lib. That is, it attempts to access the array reference contained in $lib. But wait, $lib doesn't contain an array reference. It doesn't contain anything aside from undef.
    6. Since Perl cannot dereference an entity that does not contain a reference, it throws an error and exits, unable to comply with the request. It simply will not pull a rabbit out of a hat (particularly when using strict, as you are correctly doing).

    Where you may be getting confused is over the concept of Perl's autovivification. This does work:

    use strict; use warnings; my $foo; push @$foo, 'bar';

    But this does not work:

    use strict; use warnings; my $foo; my @bar = @$foo;

    Dave

Re: Can't use an undefined value as an ARRAY reference at ./test.pl line 14.
by NetWallah (Canon) on Oct 28, 2016 at 06:01 UTC
    davido has explained WHAT the problem it.

    To answer your question on how to initialize lib :

    my $lib =[]; # A reference to an empty array
    Will resolve the issue.

    Another alternative is to check for $lib to be defined before checking scalar @$lib.

            ...it is unhealthy to remain near things that are in the process of blowing up.     man page for WARP, by Larry Wall

Re: Can't use an undefined value as an ARRAY reference at ./test.pl line 14.
by 1nickt (Canon) on Oct 28, 2016 at 12:22 UTC

    As others have pointed out, your problem is you are asking Perl to dereference a reference to a variable that has not been defined.

    This demonstrates one of the benefits of using full deference syntax rather than omitting the optional braces:

    %{ $href } # better than %$href @{ $aref } # better than @$aref
    Why better ? Besides being more readable, the full syntax allows you to put expressions in the dereference, so that in your case you could do:
    if ( scalar @{ $lib || [] } ) { ... }

    Including this because I did just get bitten by it recently:
    Also, be cautious of using scalar to test whether an array is populated. If you need to know whether there are non-empty values in the array, scalar can trip you up.

    $ perl -Mstrict -E 'my $aref = [ "", undef ]; say scalar @{ $aref || [ +] } ? "True" : "False";' True
    If you want to count only non-empty elements in your array, filter for them using grep:
    $ perl -Mstrict -E 'my $aref = [ "", undef ]; say scalar ( grep { leng +th $_ } @{ $aref || [] } ) ? "True" : "False";' False
    Hope this helps!


    The way forward always starts with a minimal test.
      the full syntax allows you to put expressions in the dereference... I did not know that, after too many years of coding Perl to admit. Thanks!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-24 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found