sub grep_and_remove (&\@) { my ($cb, $array_ref) = @_; my @found; my $src = -1; my $dst = -1; while (++$src < @{ $array_ref }) { my $match; for ($array_ref->[$src]) { $match = $cb->(); } # compact non-matches in-place of array ($match ? $found[@found] : $array_ref->[++$dst] ) = $array_ref->[$src]; } # truncate redundant end $#{ $array_ref } = $dst; return @found; }