2

I am new to Perl, and have searched long and hard for the answer to this problem, but I am stuck.

Take the following example:

my $filein = $ARGV[0];
open(SNPIN,$filein);

while(<SNPIN>)
{
   chomp;
   split(/\s+/);
   print "$_[0]\n";
}

close(SNPIN);

The test file that I am using has the following lines:

This is a test.
Is a test.
A test.

This script executes fine on our linux servers (with perl 5.10), outputting the first word of each line - although it gives me the following warning:

Use of implicit split to @_ is deprecated at scan_test.pl line 7.

but when I try to execute it on my local machine running OS X (with perl 5.12.3) I get the following error:

Useless use of split in void context at scan_test.pl line 7.
Use of uninitialized value $_[0] in concatenation (.) or string at 
scan_test.pl line 8, <SNPIN> line 1.

Obviously this is a dummy script. I have inherited someone else's extremely long and complicated script which is working on our servers but I would like to develop it locally without having to go through the entire script and reassign all default variable calls to another variable. No matter what I have tried (including "use v5.10;"), nothing will allow me to use the default variable on my local machine.

Any ideas? Help is most appreciated.

Konerak
  • 39,272
  • 12
  • 98
  • 118
rmlc
  • 21
  • 1

1 Answers1

7

It's not the platform, but the Perl version.

The warning you got on Perl 5.10 should've been a clue: deprecated means "you should not use this, because it's going to stop working in some later version". Obviously, it did stop working somewhere between Perl 5.10 and 5.12.


To fix it, just explicitly assign the list returned by split into an array. If you want to keep using @_, this should work:

chomp;
@_ = split(/\s+/);
print "$_[0]\n";

but I'd really recommend using your own named array, since @_ has a special meaning (it's used for passing parameters to subroutines):

chomp;
my @items = split(/\s+/);
print "$items[0]\n";
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
  • 2
    Correc.t Also note that `use v5.10` does not mean 'return to 5.10 compatibility mode', but rather 'require version 5.10 or higher'. – Konerak Mar 28 '12 at 05:06
  • But just out of curious interest, his main question actually seems `I would like to develop it locally without having to go through the entire script and reassign all default variable calls to another variable`. Is there a way to acknowledge this was on purpose and suppress the warning (only for this error)? – Konerak Mar 28 '12 at 05:13
  • 1
    Install the same version of Perl locally? – Greg Hewgill Mar 28 '12 at 05:21
  • Thanks for the responses, I have installed version 5.10 locally and it is behaving as expected. @Konerak you are right, I don't have the time to go through and change all the calls to the default variable in this script (which is several 000's of lines) - not to mention the many errors I would probably introduce by attempting to do so. It does seem to me that many scripts will break if updates are made to perl, why is this functionality deprecated? – rmlc Mar 28 '12 at 05:29
  • @rmlc: It was deprecated because it was something unusual and surprising (nothing else in Perl puts its return value in `@_` when used in void/scalar context) and it made it too easy to accidentally overwrite your subroutine arguments if you used `split` inside a subroutine. As for fixing your script, it should be enough to look at all the lines that generate that deprecation warning in Perl 5.10 (you _are_ logging the warnings, right?) and replace `split` with `@_ = split`. – Ilmari Karonen Mar 28 '12 at 05:51
  • 2
    Note that this is detected at compile time, so `perl -c my_script` will print all the lines where it occurs. It probably wouldn't take long to write a script to read the output from `perl -c` and do `s/split/\@_ = split/` on each line that generated the error. – cjm Mar 28 '12 at 07:26