in reply to Improve foreach with help of map?

map doesn't have special words like "last" or "next". It is really intended for situations where you want to process every single element, not for situations where you want to process just up until the first match to something or other. When you want to stop immediately on some condition your first solution, using a foreach loop is really the best choice.

However, if you really, really must use map (and I don't recommend this), you can place map inside of an eval {...} clause and "return" when you find your stop condition. Part of the attraction of map is its succinctness. As you can see from the example below, placing map inside eval {...} takes that away. More importantly, experienced Perl coders expect to see foreach or while statements when you want to "loop until stop condition" so it might take them by surprise. Taking people by surprise can really cost you need help tracking down a sneaky bug.

Normally using "return" in a map statement causes you to exit whatever sub you are currently in -- or your entire script(!) if you aren't in a sub. You probably don't want that. However, if you surround map with eval { ... } you will only leave the eval block.

#stop condition is the first empty line. use strict; use warnings; sub mapInEval { my $content = shift; my @lines; my $result; eval { # leaves eval loop, not sub @lines = map { /^$/ ? return : $_ } split /\n/, $content; return 1; }; print "non empty lines: <@lines>\n"; } sub mapNotInEval { my $content = shift; my @lines; my $result; # leaves the sub !!!! @lines = map { /^$/ ? return : $_ } split /\n/, $content; print "non empty lines: <@lines>\n"; } my $spacey = <<__EOF__; Do Re Mi __EOF__ my $notSpacey = <<__EOF__; A B C __EOF__ print "WITH eval { ... } around map\n"; print "testing spacy: "; mapInEval($spacey); print "\ntesting not spacy:"; mapInEval($notSpacey); print "------------------------------\n"; print "WITHOUT eval { ... } around map\n"; print "testing spacy: "; mapNotInEval($spacey); print "\ntesting not spacy:"; mapNotInEval($notSpacey);

Best, beth

Update: added further explanation about why using eval { map } isn't really recommended.

Replies are listed 'Best First'.
Re^2: Improve foreach with help of map?
by JavaFan (Canon) on Oct 09, 2009 at 14:27 UTC
    No need for an eval or a sub. A block will do:
    $ perl -wE '{map {say; last if /3/} 1..5}' 1 2 3
      { map { say; last if /3/ } 1..5 }
      is a contortionist's way of writing
      for (1..5) { say; last if /3/ }
      A reply falls below the community's threshold of quality. You may see it by logging in.