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, Perl
supplies a LIMIT one larger than the number of variables in the
list, to avoid unnecessary work. For the list above LIMIT
would have been 4 by default. In time critical applications it
behooves you not to split into more fields than you really
need.
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):

my $count = do {
no warnings "deprecated";
split $delim, $second;
};

6 comments:

  1. Personally, I'd just do my @parts = split $delim, $text; my $count = @parts;.

    ReplyDelete
  2. @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.

    ReplyDelete
  3. I don't understand, why you don't use such code:

    my $count = split $delim, $string;

    It works right and it's documented for split:

    In scalar context, returns the number of fields found.

    ReplyDelete
  4. @zloyrusskiy Did you miss "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"?

    ReplyDelete
  5. When dealing with the =()= operator, nothing is sacred! ;-P

    ReplyDelete
  6. @Chas

    Yes, you right, i have warning too in 5.10 version.

    ReplyDelete

Some limited HTML markup is allowed by blogger: strong, b, i, and a. You may also use em, but I have repurposed it through the magic of CSS to be behave very much like <tt><code></code></tt>.