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

as a c++ programmer, I don't have the use of a foreach loop, but I desperately need to simulate one. my question is, where during the foreach loop is the length of the list evaluated?

for example:

sub get_all_seqs{ my $protein = shift; #print "protein = $protein\n"; my @all_seqs; my %Deg_codons = get_degenerate(); my %SEQ = (); my @aas = split(//, $protein); my $aa = $aas[0]; my @codons = @{$Deg_codons{$aa}}; foreach my $codon(@codons){ $SEQ{$codon}=1; } for(my $i=1; $i<@aas; $i++){ my $aa = $aas[$i]; @codons = @{$Deg_codons{$aa}}; foreach my $seq(keys %SEQ){ foreach my $codon(@codons){ $SEQ{$seq.$codon}=1; } delete $SEQ{$seq}; } } @all_seqs = sort keys %SEQ; return @all_seqs; }


The first foreach loop inside the for loop.

where is the length of "keys %SEQ" evaluated?

Replies are listed 'Best First'.
Re: foreach to for
by GrandFather (Saint) on Jun 18, 2006 at 21:42 UTC

    Think lists and iterators. The length may not ever be evaluated in Perl - it's more complicated than that, and you don't need to know. :)

    Take a trawl through the STL and you will find equivelent constructs to foreach: for_each in <algorithm> for example.

    Update: just to make it a little clearer - Perl generates the list for the foreach "up front" before the first iteration of the loop. If your loop is over an array, the list is the array. If the loop is over something like keys of a hash or lines of a file a temporary list is generated.


    DWIM is Perl's answer to Gödel
      GrandFather,
      Update: just to make it a little clearer - Perl generates the list for the foreach "up front" before the first iteration of the loop.

      Unfortunately, the story is about as clear as mud. In recent Perl's, there are optimizations to avoid generating the entire list up front when and where possible. For instance:

      for (1 .. 2_000_000_000) { print "$_\n"; }
      You will see by checking memory consumption that the list is not generated.

      Cheers - L~R

        Unfortunately, the story is about as clear as mud.

        Agreed. The important point for OP is that it is not clear when or if Perl ever calculates the number of items. In many cases Perl simply doesn't know or care. For OP's purposes when, how or if Perl ever evaluates the number of items is actually irrelevant, but OP hasn't figured that out yet. C++ is a whole different world, but the STL does provide similarly anonymous management of lists.


        DWIM is Perl's answer to Gödel
Re: foreach to for
by chargrill (Parson) on Jun 18, 2006 at 22:23 UTC

    Word of advice, pick "for" or "foreach" and use one. Minor nit, but they're interchangable, and switching back and forth tends to make it less readable for me.

    And just a quick note:

    for( my $i=1; $i<@aas; $i++){ #etc }
    can be written more perlish as (assuming you really want elements 0 .. $#aas of @aas, instead of 1..$#aas+1):
    for( @aas ){ @codons = @{$Deg_codons{$_}}; for my $seq( keys %SEQ ){ for my $codon( @codons ){ $SEQ{$seq.$codon}=1; } delete $SEQ{$seq}; } }

    There are probably some other changes that could be made here, but these are just the ones that jump off the page at me.



    --chargrill
    $,=42;for(34,0,-3,9,-11,11,-17,7,-5){$*.=pack'c'=>$,+=$_}for(reverse s +plit//=>$* ){$%++?$ %%2?push@C,$_,$":push@c,$_,$":(push@C,$_,$")&&push@c,$"}$C[$# +C]=$/;($#C >$#c)?($ c=\@C)&&($ C=\@c):($ c=\@c)&&($C=\@C);$%=$|;for(@$c){print$_^ +$$C[$%++]}
      Word of advice, pick "for" or "foreach" and use one. Minor nit, but they're interchangable, and switching back and forth tends to make it less readable for me.
      Well, for me, I tend to use for for C-style loops (your first example) and foreach for the aliasing loops (your second example).

      I do believe a lot of people adhere to the same concept.

        And, for yet another way to do it, I follow the same pattern of for for indexing and foreach for aliasing, but I build indexing loops as
        for my $i (0..$#arr) { do_whatever(); }
        instead of doing it C-style (unless I need a more complex index transition than the usual $i++).
Re: foreach to for
by ioannis (Abbot) on Jun 19, 2006 at 09:07 UTC
    As shown bellow, the first for loop produces fixed iterations, and the second dives into infinite loop. Although expectations are not consistent, at least you get to chose which method to want.
    ## Fixed-length Loop my $i=6; for (0..$i) { print ; $i++; } #### Infinite Loop my @nums = 1..3; for (@nums) { push @nums, $_; print; }