In Perl, how can I implement map using grep?

dictionary, grep, perl

Solution

Are you sure they didn't ask how to implement `grep` with `map`? That's actually useful sometimes.

grep { STMTs; EXPR } LIST

can be written as

map { STMTs; EXPR ? $_ : () } LIST

(With one difference: `grep` returns lvalues, and `map` doesn't.)

Knowing this, one can compact

map { $_ => 1 } grep { defined } @list

to

map { defined ? $_ => 1 : () } @list

(I prefer the "uncompressed" version, but the "compressed" version is probably a little faster.)

As for implementing `map` using `grep`, well, you can take advantage of `grep`'s looping and aliasing properties.

map { STMTs; EXPR } LIST

can be written as

my @rv;
grep { STMTs; push @rv, EXPR } LIST;
@rv

Problem

Some time ago I was asked the “strange” question how would I implement `map` with `grep`. Today I tried to do it, and here is what came out. Did I squeeze everything from Perl, or there are other more clever hacks? ``` #!/usr/bin/env perl use strict; use warnings; use 5.010; sub my_map(&@) { grep { $_= $_[0]->($_) } @_[1..$#_]; } my @arr = (1,2,3,4); #list context say (my_map sub {$_+1}, @arr); #scalar context say "".my_map {$_+1} @arr; say "the array from outside: @arr"; say "builtin map:", (map {$_+1} @arr); ```

Original source