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

I thought I could do below but does not work. does split( )[ ] illegal pattern as below? I thought I could pass two argument to below sub. First argument is something like 1:3:33:2:33:5 and wanted to only store 2nd and 3rd into the array and push the second argument into it and join them by - and return the variable. Did I make program or syntax mistake or is this just not possible using below?
73 sub extract { 74 $_ = shift; 75 my @extract_i = split(/:/)[1,2]; 76 push @extract_i, $_[1]; 77 my $i_pstn = join('-', @extract_i); 78 }

Replies are listed 'Best First'.
Re: split slice?
by holli (Abbot) on Oct 13, 2007 at 22:49 UTC
    You've got two errors:
    1st you need parens around the split, and 2nd when you shift @_ it is, well, shifted. so the second argument becomes the first.

    corrected code:
    sub extract { $_ = shift; my @extract_i = (split(/:/))[1,2]; push @extract_i, $_[0]; my $i_pstn = join('-', @extract_i); }
    or shorter:
    sub extract { return join('-', (split(/:/, shift))[1,2], shift); }

      I'd be a bit worried that the second version may not perform the shifts in left to right order. There are no guarantees about the order that elements in a list are evaluated. Better would be:

      sub extract { return join('-', (split(/:/, $_[0]))[1,2], $_[1]); }

      Perl is environmentally friendly - it saves trees

        Nice. As a finishing touch, you could indicate to split to produce only 4 elements: 0 to 2, and the rest of the string in the last element to be sliced away.

        sub extract { return join('-', (split(/:/, $_[0], 4))[1,2], $_[1]); }

        • another intruder with the mooring in the heart of the Perl

      thanks!!
Re: split slice?
by Krambambuli (Curate) on Oct 14, 2007 at 06:51 UTC
    If readability and/or maintanability is of concern, it might be of help to rephrase the code somewhat like this:
    sub extract_and_add { my ($colon_sep_string, $extra_elem) = @_; my ($first, $second, $third, $ignore) = split( /:/, $colon_sep_str +ing ); return join('-', $second, $third, $extra_elem); }
    Meaningful sub and variable names are really easy to set once you get into the habit - and the extra time you'll take for that will return tenfold to you in the nearest future.

    Not to mention the gratitude of the first person after you that will have to look on the code without being forced to hold on breathing for a second to concentrate on "what exactly is meant here...?!"

    Hth.
      Another idiom I find useful and easy to understand is to simply assign the parts of the split you don't need to undef. The split would then become:

      my (undef, $second, $third, undef) = split( /:/, $colon_sep_string );

      which makes it obvious that you are not going to use the first and fourth field.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      This is true in the general case, but I think it's completely the wrong advice in the present case. Why name something you don't care about? Specifically, $first and $ignore? Notwithstanding the fact that ignore is a really bad name. So is first, second and third but I assume you just named them that way for this example.

      The slice syntax is much clearer: it indicates that whatever is in offsets 0 and beyond 2 are of no importance. And if the elements are not heterogeneous, there's no point in naming them separately as they are members of a group rather than individual elements in their own right. Thus, they have no need for names.

      I find the code you posted less readable, as I have to spend time wondering what $first and $ignore are doing, and whether some code has been left off or accidentally removed that might have done something with them. And so I have to concentrate for a second and ask myself "what exactly is meant here...?!"

      • another intruder with the mooring in the heart of the Perl