Re: Improve foreach with help of map?
by ELISHEVA (Prior) on Oct 09, 2009 at 14:17 UTC
|
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.
Best, beth
Update: added further explanation about why using eval { map } isn't really recommended.
| [reply] [d/l] [select] |
|
|
No need for an eval or a sub. A block will do:
$ perl -wE '{map {say; last if /3/} 1..5}'
1
2
3
| [reply] [d/l] |
|
|
{ map { say; last if /3/ } 1..5 }
is a contortionist's way of writing
for (1..5) { say; last if /3/ }
| [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|
Re: Improve foreach with help of map?
by toolic (Bishop) on Oct 09, 2009 at 14:08 UTC
|
In my opinion, a foreach loop is more appropriate than map in this situation.
Can you provide a compelling reason to use map here? Will your code execute significantly faster? Use much less memory? Be easier to understand and maintain?
I prefer using map for more straightforward applications, such as unconditionally transforming all elements of a list.
| [reply] |
|
|
No compelling reason, more a quest to simplify my code where possible.
| [reply] |
Re: Improve foreach with help of map?
by ikegami (Patriarch) on Oct 09, 2009 at 14:42 UTC
|
my ($result) = map /(something)/, split /\n/, $content;
Of course, map can probably easily be avoided by using the following
my ($result) = $content =~ /(something)/;
It might require small changes to the regex pattern, though | [reply] [d/l] [select] |
|
|
my ($dummy, $dummy, $result) = map /(\d\d \w\w\w \d\d\d\d)/, split /\n
+/, $content;
Instead of.
my $match = 0;
my $result = undef;
foreach(split /\n/, $content) {
if(/End Date/) { $match = 1 }
elsif($match && /(\d\d \w\w\w \d\d\d\d)/) { $result = $1; last; }
}
Thx again! | [reply] [d/l] [select] |
|
|
my ($dummy, $dummy, $result) = ...;
should be
my (undef, undef, $result) = ...;
There's also
my $result = (
map /(\d\d \w\w\w \d\d\d\d)/, split /\n+/, $content
)[2];
But really, you want the faster and more accurate
my ($result) = $content =~ /End Date.*?(\d\d \w\w\w \d\d\d\d)/s;
| [reply] [d/l] [select] |
|
|
Re: Improve foreach with help of map?
by dsheroh (Monsignor) on Oct 10, 2009 at 11:04 UTC
|
I am having a conceptual problem with this question. Or, perhaps more significantly, I suspect this question may itself reflect a conceptual problem.
As I understand it, map is a functional programming construct. One of the tenets of functional programming (at least in "pure" form) is that actions do not have side-effects. Because of this, functional constructs are inherently parallelizable.
In other words: - for/foreach runs through a list of items sequentially, allowing each one to affect the environment as it goes. This includes alterations to the loop control, such as terminating the loop early with last.
- map operates on all elements of the list independently and these operations should not affect the outside world. It is not a loop per se and this independence, if maintained, potentially allows for such things as handling elements concurrently in different contexts (multithreading/multiple CPUs/distributed systems/etc.) or optimizing the process by handling elements out-of-order. Allowing one element to abort or otherwise affect the handling of other elements violates this independence.
Based on this understanding, map is the wrong tool for this job, even if the implementation artifacts of current Perl implementations of map (i.e., behaving as if it's a loop) allow it to be coerced into doing it successfully.
Or have I misunderstood something here? | [reply] [d/l] [select] |
|
|
You're overthinking this. No need to worry about functional programming, purity, parallelisation, or any of that. The "map" concept in purely-functional programming languages is very interesting in its own right, but it has no more in common with Perl's map than mathematical functions have with Perl functions.
Perl's map is the wrong tool for the job purely because it does not do the job very well. It is good at iterating over a complete array and returning a new array, while the job was, IIUC, to iterate over part of an array and return a scalar.
If Perl's map did happen to do the job very well, then how could it be the wrong tool for it? For example, the pure FP map function must always produce exactly the same number of elements as it consumes. Perl's map can produce as many output elements as it likes for each input element, or it can skip it completely and produce nothing. In cases where that's desirable, it's perfectly appropriate to do it, without feeling guilty because a pure FP language would require an additional filtering step after the mapping was complete!
| [reply] [d/l] [select] |
Re: Improve foreach with help of map?
by JavaFan (Canon) on Oct 09, 2009 at 13:44 UTC
|
my ($result) = $content =~ /(something)/;
| [reply] [d/l] |
|
|
| [reply] |
|
|
The code I gave you gives you the first match. Without having the process the entire string splitting it into separate lines first.
| [reply] |
|
|
|
|
|
|
|
|
|
Re: Improve foreach with help of map?
by Anonymous Monk on Oct 09, 2009 at 13:39 UTC
|
Does anyone have an alternative approach to do this, using map?
Eeeew :) perldoc -f goto | [reply] |