Friday, July 9, 2010

Adventures in Ignorance: when both Perl and the Developer are too smart for their own good.

So, split returns the number of fields it would have split into when called in scalar context, but it also throws a warning in Perl 5.10: "Use of implicit split to @_ is deprecated". In an attempt to placate the warning I wrote

my $count =()= split $delim, $string;

but was surprised to find that every string returned 1. This is due to a nice little optimization that split does for you:

When assigning to a list, if LIMIT is omitted, or zero, Perlsupplies a LIMIT one larger than the number of variables in thelist, to avoid unnecessary work. For the list above LIMITwould have been 4 by default. In time critical applications itbehooves you not to split into more fields than you reallyneed.

To get around this you must specify your own limit of -1:

my $count =()= split $delim, $string, -1;

Of course, -1 doesn't have the same behavior as no limit or a limit of 0 (a limit of -1 preserves empty trailing fields), so this is not necessarily what you want. This leaves us with the last line of defense, turning off warnings (and it isn't pretty):

6 comments:

@Robert I admit it is rare that you would want to know how many fields were in a line without also wanting to know what those fields were, but in that case it is nice to not have to have the temporary variable floating around. It is also a moot point in Perl 5.12 because the warning and the behavior of splitting into @_ have both been removed. This was just one of those times where I was being too clever and Perl was being too clever at cross-purposes.