26

This code triggers the complaint below:

#!/usr/bin/perl 
use strict;
use warnings;

my $s = "aaa bbb";
my $num_of_item = split(/\s+/, $s) ;
print $num_of_item;

When I run the code, Perl complains that "Use of implicit split to @_ is deprecated" . I really have no "context" for the problem, so I expect you help to explain what's wrong with the code.

toolic
  • 57,801
  • 17
  • 75
  • 117
Haiyuan Zhang
  • 40,802
  • 41
  • 107
  • 134
  • 1
    Are you sure that you have to whole error message there? My perl also tells me the problem in on line 6. Since the split is on line 6, reading the split docs tells me the problem in the second paragraph. :) – brian d foy Mar 17 '10 at 03:10

3 Answers3

34

You are using split in scalar context, and in scalar context it splits into the @_ array. Perl is warning you that you may have just clobbered @_. (See perldoc split for more information.)

To get the number of fields, use this code:

my @items = split(/\s+/, $s);
my $num_of_item = @items;

or

my $num_of_item = () = split /\s+/, $s, -1;

Note: The three-argument form of split() is necessary because without specifying a limit, split would only split off one piece (one more than is needed in the assignment).

toolic
  • 57,801
  • 17
  • 75
  • 117
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • Or to remain concise, `my $num_of_item = () = split(/\s+/,$s)` – mob Mar 12 '10 at 22:10
  • @mobrule: your comment is belated :-) – Eugene Yarmash Mar 12 '10 at 22:13
  • 1
    That method with the () does not work for me; $num_of_item just gets set to 1. – Kevin Panko Mar 12 '10 at 22:22
  • `split` is doing something bizarre here. `my $count = @throwaway_array = split ...` works, but `my $count = () = split ...` doesn't. AFAIK something is wrong with the way split is determining its context. I wonder if p5p would agree. – hobbs Mar 12 '10 at 22:44
  • 3
    fwiw, if you don't use the `LIMIT` argument and your pattern doesn't capture, the count of `split /pattern/, $str` will just be one more than the number of times `/pattern/` matches `$str`, which you can find with an `m//g` match without using split :) – hobbs Mar 12 '10 at 22:56
  • 2
    @hobbs: Actually, this behaviour is documented in the manpage: `When assigning to a list, if LIMIT is omitted, or zero, Perl supplies a LIMIT one larger than the number of variables in the list, to avoid unnecessary work.` For the empty list LIMIT would have been 1 by default. – Eugene Yarmash Mar 12 '10 at 23:49
15

Let diagnostics provide more information:

use strict;
use warnings;
use diagnostics; # comment this out when you are done debugging

my $s = "aaa bbb";
my $num_of_item = split(/\s+/, $s) ;
print $num_of_item;

Use of implicit split to @_ is deprecated

(D deprecated, W syntax) It makes a lot of work for the compiler when you clobber a subroutine's argument list, so it's better if you assign the results of a split() explicitly to an array (or list).

A better way to get diagnostic info is from the command line:

perl -Mdiagnostics my_program.pl
Ether
  • 53,118
  • 13
  • 86
  • 159
toolic
  • 57,801
  • 17
  • 75
  • 117
  • 1
    `use diagnostics` is a real bacon-saver when it comes to getting warning messages you don't understand – mob Mar 12 '10 at 22:09
  • 1
    @mobrule: you can also simply look up these messages in `perldoc perldiag` (http://perldoc.perl.org/perldiag.html) for the longer explanation. – Ether Mar 12 '10 at 22:17
10

From the split docs:

In scalar context, returns the number of fields found. In scalar and void context it splits into the @_ array. Use of split in scalar and void context is deprecated, however, because it clobbers your subroutine arguments.

So, since you're using it in scalar context, it splits into the @_ array, which is a deprecated usage. (It has to do the split though, since it'd break old code expecting it to split into @_ - no way around the warning without assigning into a temporary array, as far as I know. Eugene Y has this explicitly in his answer.)

toolic
  • 57,801
  • 17
  • 75
  • 117
Cascabel
  • 479,068
  • 72
  • 370
  • 318