teun-arno has asked for the wisdom of the Perl Monks concerning the following question:

I have a problem with the splice function ..

my $col = 1 ; my @arr = (qw/one two three four five / ); my @indexes = ( 0 .. $#arr ) ; print ">> @arr[@indexes]\n"; print ">@indexes<\n"; # show the indexes ! my $key= splice @arr, $col,1; # remove $col from @arr. # You would expect that @indexes are NOT changed; However : print ">@indexes<\n"; # still the same indexes are shown. print "$key : @arr[@indexes]\n"; # this is NOT expected, but I do not +understand this behaviour. print ">@indexes<\n"; # still the same indexes are shown.

Output :

>> one two three four five
>0 1 2 3 4<
>0 1 2 3 4<
two : one three four five
>0 1 2 3 4<

I did not change @indexes in any way, however the splice did some nasty things!! can somebody explain ?

Replies are listed 'Best First'.
Re: splice and indexes
by johngg (Canon) on Nov 29, 2018 at 00:11 UTC

    As suggested by Anonymonk, warnings show that using your @indexes unaltered means you are trying to access a element off the end of @arr.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E ' my @arr = qw{ zero one two three four }; my @idx = ( 0 .. $#arr ); my $one = splice @arr, 1, 1; say $one; say join q{ }, @arr; say join q{ }, @idx; say join q{ }, @arr[ @idx ]; pop @idx; say join q{ }, @idx; say join q{ }, @arr[ @idx ];' one zero two three four 0 1 2 3 4 Use of uninitialized value in join or string at -e line 8. zero two three four 0 1 2 3 zero two three four

    I hope this is helpful.

    Update: Expanded example with more descriptive output.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E ' my @arr = qw{ zero one two three four }; say qq{\@arr before splice : @arr}; my @idx = ( 0 .. $#arr ); say qq{Original \@idx : @idx}; my $one = splice @arr, 1, 1; say qq{\$one from splice : $one}; say qq{\@arr after splice : @arr}; say qq{\@arr bad slice : @arr[ @idx ]}; my @newidx = ( 0 .. $#arr ); say qq{New \@newidx : @newidx}; say qq{\@arr good slice : @arr[ @newidx ]};' @arr before splice : zero one two three four Original @idx : 0 1 2 3 4 $one from splice : one @arr after splice : zero two three four Use of uninitialized value in join or string at -e line 9. @arr bad slice : zero two three four New @newidx : 0 1 2 3 @arr good slice : zero two three four

    Cheers,

    JohnGG

Re: splice and indexes
by Anonymous Monk on Nov 28, 2018 at 23:00 UTC
Re: splice and indexes
by haukex (Archbishop) on Nov 30, 2018 at 08:41 UTC

    johngg explained with code, let me try with words. You are correct that @indexes doesn't change. After the splice, your @arr has been reduced to the elements ('one','three','four','five'); I hope how splice works is clear? Then, @arr[@indexes] is attempting to access array indices 0 through 4. That works fine for the indices 0 through 3, which returns all of the remaining elements of @arr. Index 4 no longer exists in @arr, so instead, undef is returned (which is the normal behavior when accessing an array index that doesn't exist) - in other words, @arr[0..4] evaluates to ('one','three','four','five',undef). When you print those values, undef will evaluate to the empty string, and if warnings are enabled, issue a warning. This is why the suggestions from the AM post are good: always Use strict and warnings, and as per the Basic debugging checklist, when in doubt, use Data::Dumper or Data::Dump to show your variables, since they will more clearly show you undef (or whitespace in strings, etc.).