Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Write code diferently

by madM (Beadle)
on Aug 23, 2013 at 03:10 UTC ( [id://1050585]=perlquestion: print w/replies, xml ) Need Help??

madM has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks! I have this code and i would like to have it without using map.. any ideas? thanks!
map $_ /= ( $mutRate * 100), @$_ for @lnPAM; @PAM1 = map[ map exp( $_ ), @$_ ], @lnPAM; $mutRate = sum map{ $freq[ $_ ] * ( 1 - $PAM1[ $_ ][ $_ ] ) } 0..19;

Replies are listed 'Best First'.
Re: Write code diferently
by BrowserUk (Patriarch) on Aug 23, 2013 at 03:22 UTC
    i would like to have it without using map

    Why?


    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.
Re: Write code diferently
by kcott (Archbishop) on Aug 23, 2013 at 10:44 UTC

    G'day madM,

    You could probably use for loops: the map documentation has an example of this.

    Without any context for those three lines of code, or knowing the rationale behind eliminating map (as BrowserUk as already inquired about), it's difficult to know what alternative code would be suitable.

    -- Ken

Re: Write code diferently
by Random_Walk (Prior) on Aug 23, 2013 at 10:27 UTC

    You can replace map with a for loop and an assignment. There is an example of allocation to a hash with both map and a loop to be found in the map documentation http://perldoc.perl.org/functions/map.html

    From Perldoc

    Map always returns a list, which can be assigned to a hash such that the elements become key/value pairs. See perldata for more details.

    %hash = map { get_a_key_for($_) => $_ } @array;

    is just a funny way to write

    %hash = (); foreach (@array) { $hash{get_a_key_for($_)} = $_; }

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
Re: Write code diferently
by BrowserUk (Patriarch) on Aug 23, 2013 at 17:31 UTC

    Depending why you want this, there are several different was of doing it; but since you've chosen not to answer the question; here's just one.

    while( abs( $mutRate - 0.01) > 1e-16 ) { ++$iter; $k *= $mutRate * 100; # map $_ /= ( $mutRate * 100), @$_ for @lnPAM; for my $aref ( @lnPAM ) { $_ /= ( $mutRate * 100 ) for @$aref; } # @matrix = map[ map exp( $_ ), @$_ ], @lnPAM; undef @matrix; for my $aref ( @lnPAM ) { my @temp; push @temp, exp( $_ ) for @$aref; push @matrix, \@temp; } # $mutRate = sum map{ $freq[ $_ ] * ( 1 - $matrix[ $_ ][ $_ ] ) } +0..19; $mutRate = 0; for my $i ( 0 .. 19 ) { $mutRate += $freq[ $i ] * ( 1 - $matrix[ $i ][ $i ] ); } printf "After %d iteration(s), k=%13.9f, RateMutation=%19.17f\n", +$iter, $k, $mutRate; }

    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.

      but since you've chosen not to answer the question;

      One possible reason (for me): to tell the truth, the first map looks a bit clunky to me. The map function is really designed to return a 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. Clearer and possibly faster.

        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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1050585]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-04-25 18:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found