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

Perl's if statements and loop BLOCKS are bounded by curly braces. There is no ambiguity when using compound constructs and nested loops.

While attempting to convert the C code below, I was able to deduce where to block 3 loops with "curlies" as indicated by # new.

However, there are 7 places where the C program has an if statement or for loop with no obvious (to me) end. Indenting may suggest a block termination but this is only conjecture on my part and I cannot be certain the indenting is correct.

There are several C routines I want to convert with similar structures. Would a kind monk explain what rules C uses to terminate a block and then correct the code to show where the curly braces should go to make it work with Perl.

Thanks

01 sub standarization { # was standarization(void) 02 my(i,j,k); 03 for (i=1; i<=10; i++) # where does "for" end? 04 if (d[i][0]!=0) # where does "if" end? 05 for (k=1; k<24; k++) 06 { 07 d[0][k] += d[i][k]; 08 d[i][k] /= d[i][0]; 09 } 10 11 for (i=9; i<=18; i++) # where does "for" end? 12 if (psb[i][0]!=0) # where does "if" end? 13 for (k=11; k<=BUST; k++) 14 { # new 15 psb[i][k] /= psb[i][0]; 16 } # new 17 18 for (j=1; j<=10; j++) # where does "for" end? 19 if (s[j][0][0]!=0) { 20 for (i=12; i<=18; i++) { 21 if (s[j][i][0]!=0) # where does "if" end? 22 for (k=12; k<=BUST; k++) 23 { # new 24 s[j][i][k] /= s[j][i][0]; 25 } # new 26 27 if (s[j+10][i][0]!=0) # where does "if" end? 28 for (k=12; k<=BUST; k++) 29 { # new 30 s[j+10][i][k] /= s[j+10][i][0]; 31 } # new 32 s[j][i][0] /= s[j][0][0]; 33 s[j][i][1] /= s[j][0][0]; 34 s[j+10][i][0] /= s[j][0][0]; 35 s[j+10][i][1] /= s[j][0][0]; 36 } # end "for" line 20 37 38 for (k=17; k<=BUST; k++) { 39 s[j][0][k] /= s[j][0][0]; 40 s[j+10][0][k] /= s[j][0][0]; 41 } 42 } # end of "if" line 19 43 } # end of sub

Replies are listed 'Best First'.
Re: Convert loop and if constructs from C to Perl
by jbert (Priest) on Dec 16, 2006 at 09:20 UTC
    In C, an if or for applies to the following statement or block. A statement is terminated by a semi-colon. So, in C:
    for (i = 0; i < 10; ++i) printf("%d\n", i);
    is the same as:
    for (i = 0; i < 10; ++i) { printf("%d\n", i); }
    and similarly for other constructs.

    Personally, I always uses the braces in these contexts in C (as you must in perl), since I think it makes things clearer and it is more robust to future maintenance, where the potential problem is that someone may try to add a second statement to the loop but forget the braces, in which case what they have done is add a statement after the loop.

    Update: to be more correct, some statements aren't terminated by a semi-colon and sorry if that is confusing. Basically, the indentation in the code above is accurate as far as the scope of the if's and for's goes.

Re: Convert loop and if constructs from C to Perl
by bart (Canon) on Dec 16, 2006 at 09:33 UTC
    Would a kind monk explain what rules C uses to terminate a block
    If there's a block, then the rules are the same as in Perl. But if there's no block, then it's a bit more complicated.

    Basically, C expects to see either a statement, or a block. A C statement is either something straightfoward (typically an expression, but it could even be nothing) that ends in a semicolon, or it could be a if or a for control structure, or other similar control structures such those with if/else and while. If those use a block for the body, then they don't require a semicolon.

    So, if nested braceless control structures end, they all end in the same place!

    I'll not fix your code, but I'll comment it.

    You'll probably agree by now, that Perl's enforcement of use of braces for control structures, was a sane decision!

      You'll probably agree by now, that Perl's enforcement of use of braces for control structures, was a sane decision!

      That was definitely a sane decision ... but I still find it hard to accept afterthought conditions (aka "modifiers") as valid constructs.

      Yeah ... I know, I know ... it's just me :-)

      (I think in terms of "if condition, do" rather than "do, if condition" .... and nothing's gunna change that :-)

      Cheers,
      Rob
        Maybe penicillin will change your mind? /duck
      Got it!

      Thanks so much for explaining the rules along with your code comments.

      Fortunately for me, the other subs I need to convert follow a similar and consistent coding style. I'll certainly apply the rules

      And, I learned a little more about C and a lot about the wisdom behind Perl.

      Best regards, Bernie

Re: Convert loop and if constructs from C to Perl
by syphilis (Archbishop) on Dec 16, 2006 at 09:55 UTC
    Yeah, I'll have a crack at it ...
    01 sub standarization { # was standarization(void) 02 my(i,j,k); 03 for (i=1; i<=10; i++) # where does "for" end? { 04 if (d[i][0]!=0) # where does "if" end? { 05 for (k=1; k<24; k++) 06 { 07 d[0][k] += d[i][k]; 08 d[i][k] /= d[i][0]; 09 } } //end of if line 4 } //end of for line 3 10 11 for (i=9; i<=18; i++) # where does "for" end? { 12 if (psb[i][0]!=0) # where does "if" end? { 13 for (k=11; k<=BUST; k++) 14 { # new 15 psb[i][k] /= psb[i][0]; 16 } # new } //end of if line 12 } // end of for line 11 17 18 for (j=1; j<=10; j++) # where does "for" end? { 19 if (s[j][0][0]!=0) { 20 for (i=12; i<=18; i++) { 21 if (s[j][i][0]!=0) # where does "if" end? { 22 for (k=12; k<=BUST; k++) 23 { # new 24 s[j][i][k] /= s[j][i][0]; 25 } # new } // end of if line 21 26 27 if (s[j+10][i][0]!=0) # where does "if" end? { 28 for (k=12; k<=BUST; k++) 29 { # new 30 s[j+10][i][k] /= s[j+10][i][0]; 31 } # new 32 s[j][i][0] /= s[j][0][0]; 33 s[j][i][1] /= s[j][0][0]; 34 s[j+10][i][0] /= s[j][0][0]; 35 s[j+10][i][1] /= s[j][0][0]; } // end of if line 27 36 } # end "for" line 20 37 38 for (k=17; k<=BUST; k++) { 39 s[j][0][k] /= s[j][0][0]; 40 s[j+10][0][k] /= s[j][0][0]; 41 } 42 } # end of "if" line 19 } // end of for line 18 43 } # end of sub
    No guarantee I got it right, however :-)

    Cheers,
    Rob
Re: Convert loop and if constructs from C to Perl
by vladdrak (Monk) on Dec 16, 2006 at 09:10 UTC
    Perl requires you to always enclose if/elsif/else affected code in in curly braced blocks... that is, unless they occur in a post context e.g. 'print 1 if $a;'.