in reply to Re: Get fullpath of file using grep
in thread Get fullpath of file using grep

Why chain grep() and map() if you can just use grep()?

my $dir = "/tmp"; opendir my $dh, $dir or die "opendir: $!"; my @files = grep { $_ = "$dir/$_"; -f && m/\.dat$/ } readdir($dh);

It works because grep() makes $_ an alias for a list element so it can be modified in-place. Some caution is advised however (see perlfunc entry for grep() for details).

PS This code may also be a bit more efficient as it doesn't create a copy of an array returned by readdir() while doing map() but I'm not 100% sure.

Replies are listed 'Best First'.
Re^3: Get fullpath of file using grep
by choroba (Cardinal) on Jan 28, 2015 at 15:25 UTC
    Why chain grep() and map() if you can just use grep()?
    Because I agree with Perl Best Practices on "Never modify $_ in a list function" (p 114).
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Good point. However I don't think breaking this rule here is so harmful.

      As far as I get it, the advice is more relevant for grep {...} @args case when we might need the @args array later in our code. If we mess up $_ in {...} block this leads to unexpected behaviour, and thus let's play it safe. Another reason for this rule may be to keep in mind that grep() is intended as a filtering function rather then mapping one, but, ahem, we do open ... or die ... on a daily basis despite or being a logical operator and not a control flow statement.

      In this case, the grep argument is thrown away immediately so no harm done. It may not look like a textbook example but it does the job, and to my taste is reasonably more readable.

      PS Actually it's one of the quirks of being self-taught from practice rather than books - I didn't know of this rule and the book itself. But beware of dogmas - don't just follow rules blindly, try to understand them.

      Not better than chaining, but here:
      my @files = grep { my $f = "$dir/$_"; -f $f && $f =~ m/\.dat$/ } readdir($dh);