Reputation: 21503
I want to filter an array using grep
, but I want to include a warning for all filtered values, rather than silently filtering them out. I've tried this:
my @l = (1,2,3,4,5);
@l = grep {
if ($_%2 == 0) {
warn "$_ is an even number!!!";
return 0;
}
return 1;
} @l;
But this doesn't work. I get no warnings, and the list isn't filtered. How can I do this?
Upvotes: 0
Views: 199
Reputation: 954
KISS
don't try to be to smart, grep is indeed the right thing for creating a new list out of an existing list, using a positive match. Yes, you can do all sorts of fancy things inside.
but what is wrong with an ordinary foreach
?
just loop over the list, do whatever intelligent selection and push the positives onto another list. and you have an entire code block available to handle the ones you don't need and make super interesting warnings for different kind off reasons...
foreach my $item ( @numbers ) {
if ( $item %2 ) {
warn "fiz";
next
}
unless ( $item % 3 ) {
warn "buzz";
next
}
push @good, $item
}
and everyone a few days later can tell what is happening here
Upvotes: 0
Reputation: 53508
You do get warnings (you do need to use warnings; use strict;
though):
Can't return outside a subroutine
This is because grep
takes an expression or a block - it's not strictly a sub.
This will work:
#!/usr/bin/env perl
use strict;
use warnings;
my @numbers = ( 1, 2, 3, 4, 5 );
my @odd_numbers = grep {
if ( $_ % 2 == 0 ) {
warn "even number $_";
0;
}
else {
1;
}
} @numbers;
print @odd_numbers;
Also: Don't use single letter variable names. It's bad style.
Upvotes: 2
Reputation: 386696
That code dies with
Can't return outside a subroutine at a.pl line 10.
The callback isn't a subroutine. You can't use return
.
my @l = (1,2,3,4,5);
@l = grep {
if ($_ % 2) {
1
} else {
warn "even number!!!";
0
}
} @l;
Printing even number!!!
more than once isn't that useful.
my @nums = 1..5;
my @odds = grep { $_ % 2 } @nums;
warn("One or more even numbers!\n") if @odds != @nums;
Upvotes: 1