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

I have written a subroutine that parses a file and stores the data into a hash of arrays, but when I put 'use strict' in the file, it barfs. Here is the subroutine:
sub readVECFile($) { my ($filename, @fileData, $line, $vectorRef, $time, $data); local *VECTOR; # Get the filename. $filename = shift(@_); # Create a new hash. $vectorRef = { 'time' => \(), 'data' => \() }; # Open the vector file. open(VECTOR, $filename) or die("Unable to open '$filename' for reading +!\n"); # Read in the raw file data. @fileData = <VECTOR>; chomp @fileData; # Parse the time and data values out of each line, creating two arrays +. foreach $line (@fileData) { my ($t, $d); ($t, $d) = split(/\t/, $line); push(@{$vectorRef->{time}}, $t); push(@{$vectorRef->{data}}, $d); } # Close the file. close(VECTOR); return $vectorRef; }
When I try to run the script, I get the following errors:

Can't use string ("data") as an ARRAY ref while "strict refs" in use

The lines it is referencing are the 'push' lines in the foreach loop. What is going on and how do I do this while using 'strict'?

Replies are listed 'Best First'.
Re: Problems with array references and 'use strict'
by Abigail-II (Bishop) on Dec 02, 2003 at 14:28 UTC
    $vectorRef = { 'time' => \(), 'data' => \() };
    This doesn't do what you think it does. \() create a list of references to things inside the parens, making it an empty list. So, you create a reference to a hash containing just one key/value pair, 'time' being the key, 'data' being the value.

    What you want is:

    $vectorRef = {time => [], data => []};
    Or perhaps just
    $vectorRef = {};
    as Perl will happily autovivify the arrays for you.

    Abigail

Re: Problems with array references and 'use strict'
by hanenkamp (Pilgrim) on Dec 02, 2003 at 14:35 UTC

    Your problem is in the line reading:

    $vectorRef = { 'time' => \(), 'data' => \() };

    Using \() is like trying to take the address of nothing and it appears that Perl does in fact interpret this as nothing. Actually, It almost seems like this should be a warning, but use warnings doesn't complain. Running it in the perl debugger (via the -d switch) shows $vectorRef to contain the following:

    0 HASH(0x8162084) 'time' => 'data'

    Obviously, this isn't what you meant. The solution is to change each \() to [] which is the anonymous array reference constructor (less line noise too). This would make the code read:

    $vectorRef = { 'time' => [], 'data' => [] };
Re: Problems with array references and 'use strict'
by Hena (Friar) on Dec 02, 2003 at 15:15 UTC
    Monks above mentioned why this fails. But since push can handle undefined situations, it would work if you just begin with an empty hash.
    # $vectorRef = { 'time' => \(), 'data' => \() }; my $vectorRef = {};
    Update: Abigail actaully had this, so this whole answer is quite useless :P.
Re: Problems with array references and 'use strict'
by ambrus (Abbot) on Dec 03, 2003 at 12:43 UTC

    The issue is already solved. However, here are two comments.

    Some say you should $vectorRef = {}; instead of $vectorRef = { 'time' => [], 'data' => [] }; as the arrays are autovivified. However, you don't actually need to initialize $vectorRef at all, as the hash is autovivified too first time the first push statement is run.

    Also, if you still write $vectorRef = { 'time' => [], 'data' => [] }; for clarity, you don't need the quotes, as => does quoting automatically.