FAQ
Hi.

I'm new to perl, and I stumbled across a strange behavior in my for loop.
In the following code, the second for loop actually counts way passed
what I expected, and actually stops at "yz" and not "z" as expected.
As shown by the third for loop, incrementing the letters, seems to give
me the desired output in each loop.
What is going on here?


#!/usr/bin/perl
use warnings;
use strict;

my $letter = "u";

for ("u".."z"){
print " $_ ";
}

print "\n\n";

for ($_="u"; $_ le "z"; $_++){
print " $_ ";
}

print "\n\n";

for(1..7){
print " $letter ";
$letter++;
}

Search Discussions

  • Owen at Apr 13, 2010 at 6:27 am

    On Tue, 13 Apr 2010 05:35:51 +0200 Magne Sandøy wrote:

    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for
    loop. In the following code, the second for loop actually counts way
    passed what I expected, and actually stops at "yz" and not "z" as
    expected. As shown by the third for loop, incrementing the letters,
    seems to give me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";
    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }


    In the above, when $_ gets to 'y' it is less than 'z' so it
    auto increments to 'z', then when the next comparison is made, it is
    equal to 'z' and so increments again.

    I suspect auto increment is different for letters and numbers

    print "\n\n";

    for(1..7){
    print " $letter ";
    $letter++;
    }

    Which goes to show that the thing after 'z' is 'aa' using the
    auto increment




    Owen
  • Shawn H Corey at Apr 13, 2010 at 1:01 pm

    Owen wrote:
    On Tue, 13 Apr 2010 05:35:51 +0200
    Magne Sandøy wrote:
    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for
    loop. In the following code, the second for loop actually counts way
    passed what I expected, and actually stops at "yz" and not "z" as
    expected. As shown by the third for loop, incrementing the letters,
    seems to give me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";
    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }


    In the above, when $_ gets to 'y' it is less than 'z' so it
    auto increments to 'z', then when the next comparison is made, it is
    equal to 'z' and so increments again.
    At which point it becomes "aa", which is less than or equal to "z". It
    is not until it becomes "za" is it greater than "z".


    --
    Just my 0.00000002 million dollars worth,
    Shawn

    Programming is as much about organization and communication
    as it is about coding.

    I like Perl; it's the only language where you can bless your
    thingy.

    Eliminate software piracy: use only FLOSS.
  • Magne Sandøy at Apr 14, 2010 at 3:34 am

    Shawn H Corey wrote:
    Owen wrote:
    On Tue, 13 Apr 2010 05:35:51 +0200
    Magne Sandøy wrote:
    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for
    loop. In the following code, the second for loop actually counts way
    passed what I expected, and actually stops at "yz" and not "z" as
    expected. As shown by the third for loop, incrementing the letters,
    seems to give me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";
    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }


    In the above, when $_ gets to 'y' it is less than 'z' so it
    auto increments to 'z', then when the next comparison is made, it is
    equal to 'z' and so increments again.
    At which point it becomes "aa", which is less than or equal to "z".
    It is not until it becomes "za" is it greater than "z".
    Hi again.

    Thanks for all the good info. I think I have a grasp on incrementing and
    comparison, but now, what puzzles me, is the fact that when I use "le"
    less than or equal, why does it actually increment the "z"? It is by
    then passed the less than, and already at equal to "z". It should then
    just exit the loop.
    And just to add to my confusion, "ge" and "gt" does not give any output
    at all. "u" is not greatier than "z", is it?
  • Brandon McCaig at Apr 14, 2010 at 4:09 am

    2010/4/13 Magne Sandøy <msandoy@gmail.com>:
    Thanks for all the good info. I think I have a grasp on incrementing and
    comparison, but now, what puzzles me, is the fact that when I use "le" less
    than or equal, why does it actually increment the "z"? It is by then passed
    the less than, and already at equal to "z". It should then just exit the
    loop.
    And just to add to my confusion, "ge" and "gt" does not give any output at
    all. "u" is not greatier than "z", is it?
    IIRC, you're referring to this loop (from the OP):
    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }
    Note that in for loops, the 'increment' (i.e., $_++) occurs before the
    condition ($_ le "z"). So when $_ is equal to "z", the condition
    passes (i.e., $_ is less than or /equal/ to "z"). Then $_ is
    "incremented" from "z" to "aa". This too is /less than/ or equal to
    "z" using a string comparison so it continues on until it reaches
    "za", which is not.

    You may be thinking of lt instead of le. If you used lt then when $_
    was "z" it would fail the << $_ lt "z" >> condition and exit out of
    the loop right there. Because you're using le instead, you enable the
    string ordering to "wrap" back around to "aa", which starts a long
    process of "increments" before reaching something not less than or
    equal to the string "z".

    The reason gt and ge won't give any output at all is because $_ starts
    at "u", which is not greater than /nor/ equal to "z" so the condition
    fails right away.

    Forgive me if I'm misread you.

    --
    Brandon McCaig <bamccaig@gmail.com>
    V zrna gur orfg jvgu jung V fnl. Vg qbrfa'g nyjnlf fbhaq gung jnl.
    Castopulence Software <http://www.castopulence.org/> <bamccaig@castopulence.org>
  • Shlomi Fish at Apr 13, 2010 at 6:54 am
    Hi Magne,
    On Tuesday 13 Apr 2010 06:35:51 Magne Sandøy wrote:
    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for loop.
    In the following code, the second for loop actually counts way passed
    what I expected, and actually stops at "yz" and not "z" as expected.
    As shown by the third for loop, incrementing the letters, seems to give
    me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";
    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }
    "le" is the string equivalent of "<=" (less than or equal). You probably want
    "lt" instead here. A program using it yields the following:

    {{
    u v w x y z

    u v w x y

    u v w x y z aa
    }}

    Regards,

    Shlomi Fish
    print "\n\n";

    for(1..7){
    print " $letter ";
    $letter++;
    }
    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Freecell Solver - http://fc-solve.berlios.de/

    Deletionists delete Wikipedia articles that they consider lame.
    Chuck Norris deletes deletionists whom he considers lame.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • Magne Sandøy at Apr 13, 2010 at 7:37 am

    Shlomi Fish wrote:
    Hi Magne,
    On Tuesday 13 Apr 2010 06:35:51 Magne Sandøy wrote:

    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for loop.
    In the following code, the second for loop actually counts way passed
    what I expected, and actually stops at "yz" and not "z" as expected.
    As shown by the third for loop, incrementing the letters, seems to give
    me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";
    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";
    }
    "le" is the string equivalent of "<=" (less than or equal). You probably want
    "lt" instead here. A program using it yields the following:

    {{
    u v w x y z

    u v w x y

    u v w x y z aa
    }}

    Regards,

    Shlomi Fish

    print "\n\n";

    for(1..7){
    print " $letter ";
    $letter++;
    }
    Hi.

    So, what happened to the e in le, less than or "equal" to. In my
    opinion, "z" == "yz", would be incorrect, even tough that is what
    trigers the exit loop response. Try using "eq", and hopefully you
    understand my frustration.
    There has to be something I have misunderstood.

    Brgds
    Magne.
  • Shlomi Fish at Apr 13, 2010 at 7:48 am
    Hi Magne,
    On Tuesday 13 Apr 2010 10:37:15 Magne Sandøy wrote:
    Shlomi Fish wrote:
    Hi Magne,
    On Tuesday 13 Apr 2010 06:35:51 Magne Sandøy wrote:
    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for
    loop. In the following code, the second for loop actually counts way
    passed what I expected, and actually stops at "yz" and not "z" as
    expected. As shown by the third for loop, incrementing the letters,
    seems to give me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){

    print " $_ ";

    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){

    print " $_ ";

    }
    "le" is the string equivalent of "<=" (less than or equal). You probably
    want "lt" instead here. A program using it yields the following:

    {{

    u v w x y z

    u v w x y

    u v w x y z aa

    }}

    Regards,

    Shlomi Fish
    print "\n\n";

    for(1..7){

    print " $letter ";
    $letter++;

    }
    Hi.

    So, what happened to the e in le, less than or "equal" to. In my
    opinion, "z" == "yz", would be incorrect, even tough that is what
    trigers the exit loop response. Try using "eq", and hopefully you
    understand my frustration.
    "eq" will exit immediately:

    {{{
    shlomi:~$ cat t2.pl
    #!/usr/bin/perl

    use warnings;
    use strict;

    for ($_="u"; $_ eq "z"; $_++){
    print " $_ ";
    }
    print "\n";
    shlomi:~$ perl t2.pl

    shlomi:~$
    }}}

    The C-style for-loop continues as long as the condition is true and stops once
    it is false. "le" evaluates to true for all the strings in "u".."z" and beyond
    ("aa", etc.) and so the loop doesn't terminate there.

    Regards,

    Shlomi Fish
    There has to be something I have misunderstood.

    Brgds
    Magne.
    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Parody on "The Fountainhead" - http://shlom.in/towtf

    Deletionists delete Wikipedia articles that they consider lame.
    Chuck Norris deletes deletionists whom he considers lame.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • Magne Sandøy at Apr 13, 2010 at 8:17 am

    Shlomi Fish wrote:
    Hi Magne,
    On Tuesday 13 Apr 2010 10:37:15 Magne Sandøy wrote:

    Shlomi Fish wrote:
    Hi Magne,
    On Tuesday 13 Apr 2010 06:35:51 Magne Sandøy wrote:

    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for
    loop. In the following code, the second for loop actually counts way
    passed what I expected, and actually stops at "yz" and not "z" as
    expected. As shown by the third for loop, incrementing the letters,
    seems to give me the desired output in each loop.
    What is going on here?


    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){

    print " $_ ";

    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){

    print " $_ ";

    }
    "le" is the string equivalent of "<=" (less than or equal). You probably
    want "lt" instead here. A program using it yields the following:

    {{

    u v w x y z

    u v w x y

    u v w x y z aa

    }}

    Regards,

    Shlomi Fish

    print "\n\n";

    for(1..7){

    print " $letter ";
    $letter++;

    }
    Hi.

    So, what happened to the e in le, less than or "equal" to. In my
    opinion, "z" == "yz", would be incorrect, even tough that is what
    trigers the exit loop response. Try using "eq", and hopefully you
    understand my frustration.
    "eq" will exit immediately:

    {{{
    shlomi:~$ cat t2.pl
    #!/usr/bin/perl

    use warnings;
    use strict;

    for ($_="u"; $_ eq "z"; $_++){
    print " $_ ";
    }
    print "\n";
    shlomi:~$ perl t2.pl

    shlomi:~$
    }}}

    The C-style for-loop continues as long as the condition is true and stops once
    it is false. "le" evaluates to true for all the strings in "u".."z" and beyond
    ("aa", etc.) and so the loop doesn't terminate there.

    Regards,

    Shlomi Fish

    There has to be something I have misunderstood.

    Brgds
    Magne.
    Hi again.

    Does this mean this is a bug?
    My point is to get "z" at the end. Using "eq" or lt" wont work.
    Brgds
    Magne
  • Shlomi Fish at Apr 13, 2010 at 8:58 am
    On Tuesday 13 Apr 2010 11:17:12 Magne Sandøy wrote:
    [SNIP]
    Hi again.

    Does this mean this is a bug?
    It's not a bug - this is how it works.
    My point is to get "z" at the end. Using "eq" or lt" wont work.
    You need to evaluate the condition at the end of the loop instead of at the
    beginning. Try doing something like that (tested):

    {{{
    #!/usr/bin/perl

    use warnings;
    use strict;

    sub process_letter
    {
    my $letter = shift;

    print "$letter\n";
    }

    my $letter = "u";

    LETTERS_LOOP:
    while (1)
    {
    process_letter($letter);

    if ($letter eq "z")
    {
    last LETTERS_LOOP;
    }
    }
    continue
    {
    $letter++;
    }

    }}}

    It's a bit ugly and I've erred a bit on using pseudo-Hungarian Notation ( see
    http://en.wikipedia.org/wiki/Hungarian_notation ) - for the sake of the
    demonstration, but it works.

    Hope it helps.

    Regards,

    Shlomi Fish

    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Original Riddles - http://www.shlomifish.org/puzzles/

    Deletionists delete Wikipedia articles that they consider lame.
    Chuck Norris deletes deletionists whom he considers lame.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • C.DeRykus at Apr 13, 2010 at 12:35 pm

    On Apr 12, 8:35 pm, msan...@gmail.com (Magne Sandøy) wrote:
    Hi.

    I'm new to perl, and I stumbled across a strange behavior in my for loop.
    In the following code, the second for loop actually counts way passed
    what I expected, and actually stops at "yz" and not "z" as expected.
    As shown by the third for loop, incrementing the letters, seems to give
    me the desired output in each loop.
    What is going on here?

    #!/usr/bin/perl
    use warnings;
    use strict;

    my $letter = "u";

    for ("u".."z"){
    print " $_ ";

    }

    print "\n\n";

    for ($_="u"; $_ le "z"; $_++){
    print " $_ ";

    }

    print "\n\n";

    for(1..7){
    print " $letter ";
    $letter++;

    }
    This is the trickiness of magical autoincrement. See: perldoc perlop.

    Once, you increment $_ = 'z' in your loop:

    perl -le "$_='z';$_++; print" ---> prints 'aa';

    And, the incrementing continues until, finally, you reach 'yz':

    perl -le "$_='yz';$_++; print $_" ---> prints 'za'

    Why did it stop at 'yz'... you ask... Because the string 'za'
    would generate a value 'longer than z' itself .

    Similiarly, if your range had been 'uu'..'zz', the increment
    would have stopped at 'zyz' because incrementing would
    then produce 'zza'.

    Clear as mud? Did you say 'Hell, no'...? Go then and
    meditate on autoincrement magic, grasshopper. When
    enlightenment comes, please report back and explain it
    to us too...

    --
    Charles DeRykus
  • Shawn H Corey at Apr 13, 2010 at 3:54 pm

    C.DeRykus wrote:
    Clear as mud? Did you say 'Hell, no'...? Go then and
    meditate on autoincrement magic, grasshopper. When
    enlightenment comes, please report back and explain it
    to us too...
    Actually, it is because string-comparison operators order strings
    differently than auto-increment.

    String ordering by auto-increment:
    "a"
    "b"
    ...
    "y"
    "z"
    "aa"
    "ab"
    ...
    "yy"
    "yz"
    "za"
    "zb"
    ...

    String ordering by string-comparison operators:
    "a"
    "aa"
    "aaa"
    ...
    "y"
    "ya"
    "yaa"
    ...
    "yz"
    "yzz"
    "yzzz"
    ...
    "z"
    "za"
    "zaa"
    ...

    Notice that "z" appears in very different place in each.


    --
    Just my 0.00000002 million dollars worth,
    Shawn

    Programming is as much about organization and communication
    as it is about coding.

    I like Perl; it's the only language where you can bless your
    thingy.

    Eliminate software piracy: use only FLOSS.
  • C.DeRykus at Apr 13, 2010 at 5:49 pm

    On Apr 13, 8:54 am, shawnhco...@gmail.com (Shawn H Corey) wrote:
    C.DeRykus wrote:
    Clear as mud?  Did you say 'Hell, no'...?  Go then and
    meditate on  autoincrement magic,  grasshopper. When
    enlightenment comes, please report back and  explain it
    to us too...
    Actually, it is because string-comparison operators order strings
    differently than auto-increment.

    String ordering by auto-increment:
    "a"
    "b"
    ...
    "y"
    "z"
    "aa"
    "ab"
    ...
    "yy"
    "yz"
    "za"
    "zb"
    ...

    String ordering by string-comparison operators:
    "a"
    "aa"
    "aaa"
    ...
    "y"
    "ya"
    "yaa"
    ...
    "yz"
    "yzz"
    "yzzz"
    ...
    "z"
    "za"
    "zaa"
    ...

    Notice that "z" appears in very different place in each.
    Yes, you're right. But I mentioned "enlightenment" because
    the auto-increment algorithm itself is somewhat mysterious.
    And, here's the doozy for me as I tried remembering:

    If the final value specified is not in the sequence that the
    magical increment would produce, the sequence continues
    until the next value is longer than the final value specified.
    ^^^^^^

    So, in the OP's 'u'..'z' example, the expansion stops at 'yz'
    because another increment would be 'za' which is 'longer'
    than the final value specified'; whereas, 'yz' isn't:

    'z' 122
    'aa' 97 97
    ...
    'yz' 121 122 ---> 'shorter' than 122
    'za' 122 97 ----> 'longer' than 122

    In other words, the sequencing continues until there's
    carry past the final 'z'. I think that's the 'long and short
    of it... maybe I've auto-enlightened myself..

    --
    Charles DeRykus
  • Shawn H Corey at Apr 14, 2010 at 12:22 pm

    C.DeRykus wrote:
    And, here's the doozy for me as I tried remembering:

    If the final value specified is not in the sequence that the
    magical increment would produce, the sequence continues
    until the next value is longer than the final value specified.
    ^^^^^^

    So, in the OP's 'u'..'z' example, the expansion stops at 'yz'
    because another increment would be 'za' which is 'longer'
    than the final value specified'; whereas, 'yz' isn't:
    Actually, no. "z" is in the sequence, so it stops there.

    Try:

    for ( 'u' .. ' ' ){
    print "$_ ";
    }
    print "\n";


    --
    Just my 0.00000002 million dollars worth,
    Shawn

    Programming is as much about organization and communication
    as it is about coding.

    I like Perl; it's the only language where you can bless your
    thingy.

    Eliminate software piracy: use only FLOSS.
  • C.DeRykus at Apr 14, 2010 at 2:57 pm

    On Apr 14, 5:22 am, shawnhco...@gmail.com (Shawn H Corey) wrote:
    C.DeRykus wrote:
    And, here's the doozy for me as I tried remembering:
    If the final value specified is not in the sequence that the
    magical increment would produce, the sequence continues
    until the next value is longer than the final value specified.
    ^^^^^^
    So, in the OP's 'u'..'z' example,  the expansion stops at 'yz'
    because another increment would be 'za' which is 'longer'
    than the final value specified'; whereas, 'yz' isn't:
    Actually, no.  "z" is in the sequence, so it stops there.

    Try:

    for ( 'u' .. ' ' ){
    print "$_ ";}

    print "\n";

    No, the OP was talking about the *second* 'for' loop of course --
    not
    the first loop which obviously works.


    OP> In the following code, the second for loop actually counts way
    OP> passed what I expected, and actually stops at "yz" and not "z"
    OP> as expected.


    The 'u'..'z' mis-identifies the loop but the context is clear as to
    which
    loop was being discussed.


    --
    Charles DeRykus

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedApr 13, '10 at 3:36a
activeApr 14, '10 at 2:57p
posts15
users6
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase