to tell the truth, the first map looks a bit clunky to me.
Truth is good; but "looks a bit clunky to me" doesn't cut much ice as a technical objection. It reflects only your own limited expectations.
The map function is really designed to return a list.
Repeating cargo cult does not make it so.
map maps a function over a list; optionally returning a new list. Used in a void context; it does not create an output list.
If you are using it only for its side effects on $_ and therefore on the original list, then I submit that for/foreach is a better choice.
In the abstract, that is sound reasoning; but it concentrates on the minutia rather than the bigger picture.
The purpose of that line of code is to apply a function: f(x) := x / (mutation rate * 100); in place, to every element of a matrix.
The original language, Darwin, has matrix operators that allow this to be written very naturally.
Perl does not have those operators; but does provide the tools to allow them to be written quite concisely. Thus allowing the purpose of the code; the mutation of the elements of the matrix to stand clear of the mechanics of the code required to iterate over the matrix dimensions.
I contend that this:
for my $aref ( @lnPAM ) {
$_ /= ( $mutRate * 100 ) for @$aref;
}
Distracts from the purpose of the code, by making too great an emphasis of the (purely mechanical) process of iterating the matrix.
Clearer and possibly faster.
Clearer is in the eye of the beholder -- and I disagree with your view.
Faster is a matter of benchmarking, but my guess is that there will be little in it; and it will probably favour the map version: @a = map[ map int(rand$_), 1 .. 10],1..10;;
cmpthese -1,{
a=>q[ map $_ /= 1, @$_ for @a; ],
b=>q[ for my $r( @a ){ $_ /= 1 for @$r } ],
};;
Rate b a
b 52726/s -- -25%
a 70388/s 33% --
Yup!
The perl code: while( abs( $mutRate - 0.01) > 1e-16 ) {
++$iter;
$k *= $mutRate * 100;
map $_ /= ( $mutRate * 100), @$_ for @lnPAM;
@matrix = map[ map exp( $_ ), @$_ ], @lnPAM;
$mutRate = sum map{ $freq[ $_ ] * ( 1 - $matrix[ $_ ][ $_ ] ) } 0.
+.19;
printf "After %d iteration(s), k=%f, RateMutation=%f\n", $iter, $k
+, $mutRate;
}
was written to mirror the original Darwin code: while abs(RateMutation - 0.01) > DBL_EPSILON do
iter := iter + 1;
k:= k * RateMutation * 100:
lnPAM1 := lnPAM1 / (RateMutation * 100):
PAM1 := exp(lnPAM1):
RateMutation := sum(Freq[i] * (1 - PAM1[i,i]), i= 1..20);
printf('After %d iteration(s), k=%f, RateMutation=%f', iter, k, Ra
+teMutation);
od:
as closely as possible; which I think it does admirably.
The reason for asking the OP why he wanted it coded a different way; was so as to get some idea of how best to address his concerns when doing so.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|