Ascii characters in a loop

M

Mark Hobley

The following loop works fine in Perl:

for ($l = 'a'; $l le 'y'; $l++) {
print "$l";
}

However, if I try to loop from a through to z, the loop does not work:

for ($l = 'a'; $l le 'z'; $l++) {
print "$l";
}

I know that a for each loop would work, but that is not what I want.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
R

RedGrittyBrick

Mark said:
The following loop works fine in Perl:

for ($l = 'a'; $l le 'y'; $l++) {
print "$l";
}

However, if I try to loop from a through to z, the loop does not work:

It does but it produces results you might not have expected.
for ($l = 'a'; $l le 'z'; $l++) {
print "$l";
}

Because of the way the post-increment operator works on strings.
See `perldoc perlop` under Auto-increment.

The value after 'z' is 'aa' and 'aa' is still stringwise less than 'z'.

Luckily 'zz' is greater than 'z'.
 
R

RedGrittyBrick

RedGrittyBrick said:
It does but it produces results you might not have expected.


Because of the way the post-increment operator works on strings.
See `perldoc perlop` under Auto-increment.

The value after 'z' is 'aa' and 'aa' is still stringwise less than 'z'.

Luckily 'zz' is greater than 'z'.

Oh yes,

Why exactly don't you want a foreach loop?

C:\>perl -e "for $x ('a'..'z') { print \"$x,\";}"
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,

C:\>perl -e "$e='z'; for $x ('a'..$e) { print \"$x,\";}"
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
 
M

Mark Donovan

The following loop works fine in Perl:

for ($l = 'a'; $l le 'y'; $l++) {
print "$l";
}

However, if I try to loop from a through to z, the loop does not work:

for ($l = 'a'; $l le 'z'; $l++) {
print "$l";
}

I know that a for each loop would work, but that is not what I want.

I think you're expecting: abcdefghijklmnopqrstuvwxyz

And if that's what you want, you must use ne instead of le to end the loop.

for ($l = 'a'; $l ne 'z'; $l++) {
print "$l";
}

If you replace
print "$l";
with
print "$l ";
you can see what's happening. Change the comparison from le the ne, and the
loop stops at z, but with le, the loop does not stop until zz is less than
z.

Try this little experiment.

print join(' ', sort qw( a b c x y z aa bb cc xx yy zz )), "\n";

There are two things happening in your second loop. First, Auto-increment
for string data is smarter than you expect, maybe too smart. The next value
after z is aa. Second, operators like lt, le, eq, ne, ge, and gt are
stringwise comparisons. This means the result of a comparison reflects the
sorting order of the strings, and as you see from the experiment, aa is less
than z.
 
J

John Bokma

Mark Donovan said:
On 1/13/07 16:04, in article (e-mail address removed),
[..]

for ($l = 'a'; $l le 'z'; $l++) {
print "$l";
}

I know that a for each loop would work, but that is not what I want.

I think you're expecting: abcdefghijklmnopqrstuvwxyz

And if that's what you want, you must use ne instead of le to end the
loop.

No, 'aa' Which might confuse a lot of people.
for ($l = 'a'; $l ne 'z'; $l++) {
print "$l";
}

abcdefghijklmnopqrstuvwxy

for ($l = 'a'; $l ne 'aa'; $l++) {
print "$l";
}

abcdefghijklmnopqrstuvwxyz

If you replace
print "$l";
with
print "$l ";
you can see what's happening. Change the comparison from le the ne,
and the loop stops at z,

but doesn't reach the print ;-)
 
J

John Bokma

RedGrittyBrick said:
Oh yes,

Why exactly don't you want a foreach loop?

My guess: because he wants to know why this one "doesn't work" instead of
reading: "use this instead".

To me it was educational (as in if someone has asked to write that loop
like that I am sure it would have bitten me as well), so thanks OP :)
 
M

Mark Hobley

John Bokma said:
My guess: because he wants to know why this one "doesn't work" instead of
reading: "use this instead".

I am writing Perl documentation. All these points seem to be missed in the
reference books that I am using, which incidently are extremely big and run
into several thousand pages each and cost me quite a few quid.

It seems strange that if I increment $l (which equals 'z') then I now have a
value that is comparitively less than 'z'.

This looks like a bug to me, at least in the context of an a to z loop.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
D

Dr.Ruud

Mark Hobley schreef:
The following loop works fine in Perl:

for ($l = 'a'; $l le 'y'; $l++) {
print "$l";
}

However, if I try to loop from a through to z, the loop does not work:

for ($l = 'a'; $l le 'z'; $l++) {
print "$l";
}

It does work, but not in the way that you suspect(ed).
See also perldoc -q quoting.

I know that a for each loop would work, but that is not what I want.

Better mention what you do want.
 
R

RedGrittyBrick

Mark said:
I am writing Perl documentation. All these points seem to be missed in the
reference books that I am using, which incidently are extremely big and run
into several thousand pages each and cost me quite a few quid.

It seems strange that if I increment $l (which equals 'z') then I now have a
value that is comparitively less than 'z'.

This looks like a bug to me, at least in the context of an a to z loop.

Probably because you are thinking "for $x := 'a' to 'z'" but writing
something completely different.

In my view, you *don't* have an a to z loop. You have an initializer;
loop-test; counting-expression loop.

I've always disliked them, I find they're mostly used for shooting
yourself in the foot or doing something more clearly expressed as a
foreach or numeric-range loop.

http://en.wikipedia.org/wiki/For_loop#Kinds_of_for_loops


Saying "in the context of" suggests that you'd like 'z' le 'aa' to
sometimes return true and sometimes return false depending in whether
the expression was being evaluated in the context of a for loop or not.

I think that would be a bad thing. In the code below the value returned
by my inorder subroutine would have to depend on whether it was called
from an expression that was part of a for loop. This would be horribly
hard to justify.

#!perl
use strict;
use warnings;

if (inorder('aa','z')) { print 'ordered OK'; }

for (my $x='x'; inorder($x, 'z'); $x++) {
print $x,' ';
}

sub inorder {
my ($p, $q) = @_;
$p le $q;
}

And of course, if you are using a three-part for loop to sort a
dictionary you'd want the current behaviour of the le operator even in
the context of a for loop.
 
M

Mark Hobley

John Bokma said:
for ($l = 'a'; $l ne 'aa'; $l++) {
print "$l";
}

Yeah! I just think that 'a to z' looks far nicer late on a Friday night when I
am trying to debug code.

I need to test reverse loops, capitals, jumping by more than one letter at a
time now to see if there are any more nasty surprises.

I often loop through alphabetical sequences in code.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
M

Mark Hobley

Dr.Ruud said:
Better mention what you do want.

I am documenting Perl and at the moment I am documenting loops, so I need to
know any place where choosing a particular value will cause different behaviour
than choosing another value.

I often use alphabetical increments in code, so anywhere that choosing a
particular values for alphabetical ranges requires a change in syntax to
perform across those range needs to be noted.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
U

Uri Guttman

MH> I am documenting Perl and at the moment I am documenting loops, so
MH> I need to know any place where choosing a particular value will
MH> cause different behaviour than choosing another value.

what is this 'documenting perl'? perl IS documented and very well at
that. and there are tons of books about perl. what do you expect to
bring to the table and make it worthy of reading?

MH> I often use alphabetical increments in code, so anywhere that choosing a
MH> particular values for alphabetical ranges requires a change in syntax to
MH> perform across those range needs to be noted.

there is no need to worry about this if you understand the rules of
magic incrementing strings. they are well documented under ++ and .. in
perlop. and in general it makes little sense to code them using c style
for loops. (in fact c style for loops are RARELY needed in perl). use
... for looping over a range of incrementing strings.

uri
 
U

Uri Guttman

MH> Yeah! I just think that 'a to z' looks far nicer late on a Friday
MH> night when I am trying to debug code.

MH> I need to test reverse loops, capitals, jumping by more than one
MH> letter at a time now to see if there are any more nasty surprises.

what is a reverse loop? perl has no such beast. perldoc perlop covers
magic increment, have you read it?

MH> I often loop through alphabetical sequences in code.

then you must be the odd one. i rarely do and i rarely see it. it is
useful and i use it but often??

uri
 
J

John Bokma

This looks like a bug to me, at least in the context of an a to z
loop.

I am sure most will call it a feature, that 'z'++ goes to 'aa'.

As for loops, the form you use is in my experience very rare. I would have
used:

for my $l ( 'a' .. 'z' ) {

}

Less cluter, and much easier to understand.
 
P

Peter J. Holzer

I am writing Perl documentation. All these points seem to be missed in the
reference books that I am using, which incidently are extremely big and run
into several thousand pages each and cost me quite a few quid.

It seems strange that if I increment $l (which equals 'z') then I now have a
value that is comparitively less than 'z'.

That's because the "le" operator doesn't define "less" and "greater" in
the same sense as "++" increments. The same happens if you use numbers:

for (my $l = 0; $l le 9; $l++) {
print "$l ";
}

prints

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

Because 90 is the first number which is greater than 9 in a string
comparison.

Only with numbers there is a simple solution (use "<=" instead of "le"),
while there is no builtin comparison operator for "alphanumeric
numbers".

hp
 
M

Mark Hobley

Uri Guttman said:
what is a reverse loop?

I meant a decremental loop that goes from a higher value to a lower one.

perl has no such beast. perldoc perlop covers
magic increment, have you read it?

I have now, but I don't think it is really that clear.
MH> I often loop through alphabetical sequences in code.
then you must be the odd one. i rarely do and i rarely see it.

I write educational software, games, data processing and back-end stuff. Maybe
they are more prevalent in these.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
M

Mark Hobley

Uri Guttman said:
what is this 'documenting perl'? perl IS documented and very well at
that. and there are tons of books about perl. what do you expect to
bring to the table and make it worthy of reading?

Tutorial stuff really. I have read tutorials, but I keep finding quirky
behaviour that the tutorials forgot to mention.

I don't like perldoc. It is difficult to digest, and doesn't give enough
examples, and the reference books that I have spent a small fortune on, don't
mention some of the pitfalls that I am encountering.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
U

Uri Guttman

MH> Tutorial stuff really. I have read tutorials, but I keep finding
MH> quirky behaviour that the tutorials forgot to mention.

almost all perl tutes on the web suck donkey dick. everytime i hear of
one i check it out and see how fast i can find stupid bugs and
comments. i have rarely been disappointed. in my future copious spare
time i will make a page of perl tutes hall of shame.

MH> I don't like perldoc. It is difficult to digest, and doesn't give
MH> enough examples, and the reference books that I have spent a small
MH> fortune on, don't mention some of the pitfalls that I am
MH> encountering.

you don't understand that perldoc is documentation and not tutorial. but
there are a fair number of tutes in there now.

just as a warning to you, writing perl tutes is not easy (witness all
the bad ones out there). if you have trouble reading and comprehending
the existing docs (as with your magic increment issue) bodes poorly for
your proposed tute. i could be wrong but the odds are with me. i know
many perl book authors and how sharp they are and how much perl they
know. to write a tute you need to know more perl than most hackers,
write extremely well, be able to express concepts clearly, concisely and
have plenty of good examples. this is a tough task for anyone.

uri
 
D

Dr.Ruud

Mark Hobley schreef:

I don't like perldoc. It is difficult to digest, and doesn't give
enough examples, and the reference books that I have spent a small
fortune on, don't mention some of the pitfalls that I am encountering.

Actually a nice title for an article: Perl Pitfalls. Last week (and not
here) we discussed Tropical Perl, a book about how far you can get with
Perl in a don't-worry-be-happy style. Perl Pitfalls can be about things
like using 'le' when you shouldn't and about how to solidly spoil the
value of $_ && about how to be bitten best by binops.
 
U

Uri Guttman

MH> perl has no such beast. perldoc perlop covers
MH> I have now, but I don't think it is really that clear.

clear to me.

The auto-increment operator has a little extra builtin magic
to it. If you increment a variable that is numeric, or that
has ever been used in a numeric context, you get a normal
increment. If, however, the variable has been used in only
string contexts since it was set, and has a value that is
not the empty string and matches the pattern
"/^[a-zA-Z]*[0-9]*\z/", the increment is done as a string,
preserving each character within its range, with carry:

print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
print ++($foo = 'Az'); # prints 'Ba'
print ++($foo = 'zz'); # prints 'aaa'

what part of that do you find unclear? it shows the rollover case in
numeric and similarly to your example with zz -> aaa.

MH> I often loop through alphabetical sequences in code.
MH> I write educational software, games, data processing and back-end
MH> stuff. Maybe they are more prevalent in these.

i doubt that. i have coded many different projects and don't see string
increment being needed often. but you could be using the only hammer you
have to work on different nails. i see that all the time.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top