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

Hello Arbiters of Good Hope,

I am a relative newbie to any kind of coding and just took up using perl after learning the basics in python.

I've not quite got the hang of the 'for' loop syntax; say for example this chunk of code:

use Text::CSV_XS qw(csv); my @sig; print "Enter file name: \n"; my $file = <STDIN>; chomp $file; my $csv = Text::CSV_XS->new({binary => 1}); open (INPUT, $file) || die("Could not find $file"); while (my $line = <INPUT>) ## Pushing values from csv into the array { push @sig, <INPUT>, $_; for (my $i; ($i<=scalar @sig); $i++){ for (my $j=($i+1); ($j<=scalar@sig); $j++){ print "@sig[$j]\n"; } } close; }

Brings me back a compilation error referring to the for loops, as far as I can see they look correct but what the hell do I know. Can anyone help a poor man out of his blind state?

Replies are listed 'Best First'.
Re: For loop abortions
by AnomalousMonk (Archbishop) on Mar 18, 2016 at 03:21 UTC

    If you're a beginner (and even if you're not), it's almost always a good idea to  usewarnings; and  usestrict; in all your scripts. Take a look at the warnings (not errors) below and try to fix them, then come back for more enlightenment.

    c:\@Work\Perl\monks\Sellerzzz>type text line 1 second line line the third c:\@Work\Perl\monks\Sellerzzz>perl -e "use warnings; use strict; ;; my @sig; ;; print \"Enter file name: \n\"; my $file = <STDIN>; chomp $file; ;; open (INPUT, $file) || die(\"Could not find $file\"); while (my $line = <INPUT>) { push @sig, <INPUT>, $_; for (my $i; ($i<=scalar @sig); $i++){ for (my $j=($i+1); ($j<=scalar@sig); $j++){ print \"@sig[$j]\n\"; } } close; } " Scalar value @sig[$j] better written as $sig[$j] at -e line 1. Enter file name: text Use of uninitialized value $i in numeric le (<=) at -e line 1, <INPUT> + line 3. Use of uninitialized value $i in addition (+) at -e line 1, <INPUT> li +ne 3. line the third Use of uninitialized value $sig[2] in join or string at -e line 1, <IN +PUT> line 3. Use of uninitialized value in join or string at -e line 1, <INPUT> lin +e 3. Use of uninitialized value $sig[2] in join or string at -e line 1, <IN +PUT> line 3. Use of uninitialized value in join or string at -e line 1, <INPUT> lin +e 3. Use of uninitialized value in join or string at -e line 1, <INPUT> lin +e 3.
    I have taken out the use of Text::CSV_XS in the example code since it adds nothing to the point I want to make. BTW: congratulations on the use of a nice Short, Self Contained, Correct (Compilable), Example; pursue the problems it highlights and you will be well on your way to wisdom.


    Give a man a fish:  <%-{-{-{-<

Re: For loop abortions
by choroba (Cardinal) on Mar 17, 2016 at 22:17 UTC
    What error did you get? I'm getting none, only a warning unrelated to the for loops:
    Scalar value @sig[...] better written as $sig[...] at -e line 15.

    It just means that with a single index, you should rather write $sig[$j] .

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: For loop abortions
by Laurent_R (Canon) on Mar 17, 2016 at 22:36 UTC
    I don't see any syntax error in your for loops, but they might be written in a simpler and less error-prone fashion with something like this:
    for my $i (0..$#sig) { for my $j ($i+1..$#sig) { print "$sig[$j]\n"; } }
    Perhaps it could be made even simpler, but I don't understand well enough what you intend to do to be able to suggest something that might get rid of one of the loops variables.

    Update: Another possible way:

    for my $i (0..$#sig) { for my $item (@sig[$i+1..$#sig]) { print "$item\n"; } }
    second update: fixed an off-by-one error in the first piece of code. Thanks to AnomalousMonk for pointing it out.

    third update: fixed yet another an off-by-one error . Thanks to AnomalousMonk for pointing it out.

      But the outer  for my $i (0..scalar @sig) { ... } in both loop examples still seems to me to have an inherent off-by-one error. This error is masked by the fact that  $#sig is used as the range limit in the  $i+1..$#sig range expression of both inner loops.

      But the inherent error (as I consider it) still remains, and must be fixed up or masked or otherwise dealt with in some way, and poses a potential pitfall for future programmers and maintainers. Why not use the more idiomatic (and IMHO correct)  for my $i (0 .. $#sig) { ... } form in both outer loops?


      Give a man a fish:  <%-{-{-{-<

        Yes, you are absolutely right, AnomalousMonk, I copied and pasted part of the original code too hastily. This is still quite messy, even if it works.

        I'll fix that for future reference immediately after my answer.

        The other point is that I am not convinced by the algorithm and I suspect it is probably not really what the OP wants, I have trouble finding a use case that would really make sense out of that, but I do not know what the OP wants would really and we don't have enough information, at least not at this point, to be sure.

        Thank you very much.