Re: the '..' operator and decreasing values
by ikegami (Patriarch) on Mar 04, 2005 at 22:27 UTC
|
.. always counts up. I don't know why, but this workaround will do the trick:
for ( 0 .. 10 ) {
my $i = 10 - $_;
# do something
}
| [reply] [d/l] [select] |
|
for (reverse 0..10) { ... }
| [reply] [d/l] |
|
Let's hope the list isn't too long. for (0..x) is evaluated lazily, but I doubt that for (reverse x..0) is as well.
On second thought, that would rarely matter.
| [reply] [d/l] [select] |
|
|
|
|
|
| [reply] |
Re: the '..' operator and decreasing values
by Taulmarill (Deacon) on Mar 04, 2005 at 22:31 UTC
|
for my $i ( reverse ( 0 .. 10 ) ) {
print "$i\n";
}
| [reply] [d/l] |
Re: the '..' operator and decreasing values
by cog (Parson) on Mar 04, 2005 at 23:27 UTC
|
If you think about it, it makes sense; it's not "all values between X and Y", but rather "all values greater than X and lower than Y".
If Y is smaller than X, of course, you get an empty list, but that can really be helpful, in some cases. | [reply] |
|
Actually, its all values greater than OR EQUAL to X, and less than OR EQUAL to Y.
| [reply] |
Re: the '..' operator and decreasing values
by eXile (Priest) on Mar 04, 2005 at 22:42 UTC
|
thanks for the replies everybody, I already had a workaround (although that wasn't clear for the OP), and was just curious if anybody knows why this doesn't work as I expected, and why it returns an empty list. If I wanted to see if one value is bigger than the other, I could have simply compared them, I don't need '..' for that. | [reply] |
|
The range operator uses the magic increment operator internally so that it can work on strings (i.e, 'a'..'zzz'). Since there is no corresponding magic decrement operator, it doesn't work in reverse. You could make the argument that for numeric endpoints, you don't need the increment/decrement to be magical, but this is the way it is...
| [reply] |
|
Well, contrariwise, it's useful in its current form if you want to be able to short-circuit out empty lists without having to do an explicit test. For (contrived, but based on a real-world memory) example:
sub contrivance {
my $min = shift;
my $max = some_function();
for ($min .. $max) {
print "I think that $_ is a valid possibility\n";
}
}
Contrived, as I said. But the point is that you can readily find a family of uses for the range operator where you'd want to return an empty list rather than counting backward if the RHS is less than the LHS, just as you can (and indeed, you have) for the opposite. Apparently, Larry thought my use case was more common than yours—lucky me, huh? :-)
If God had meant us to fly, he would *never* have given us the railroads. --Michael Flanders
| [reply] [d/l] |
|
| [reply] |
Re: the '..' operator and decreasing values
by phroggy (Monk) on Mar 05, 2005 at 00:25 UTC
|
That's roughly equivalent to:
for(my $i=10;$i<=0;$i++) {
# do something
}
You can't use .. to count backwards, but try this:
for my $i (reverse 0..10) {
# do something
}
for $a(-2,12){for $b(0..7){$c=0;$_?hex substr(
ef7fa1866706caeff02289402844,2*$_+$a,2)&2**(7-$b):0
and $c+=2**(7-$_)for(0..7);print chr $c;}}
| [reply] [d/l] [select] |
|
for ( my $i = 10; $i--; ) {
# do something
}
I regularly walk array indexes backwards, as you can shave a few cycles off of the standard for ( my $i = 0; $i < $array_size; $i++ ) {
# whatever
}
logic that people love using in those languages that don't have a 'foreach' command. | [reply] [d/l] [select] |
Re: the '..' operator and decreasing values
by SolidState (Scribe) on Mar 06, 2005 at 16:57 UTC
|
does anybody know why this behaviour was chozen?
More important, I think, is the question "why doesn't use warnings; warn about this?
I think this is the real question here. I too have been bitten by this behaviour and while it didn't cost me hours to debug, it did slow me down and was annoying to find.
I don't know why use warnings; doesn't warn about this. I wish it did :-(
After all, we already get messages such as "Useless use of a constant in void context at...". Why not something like "Useless use of an empty list in loop context at...", or something similiar.
Just my 2 cents worth...
| [reply] |
|
Because that would be another useless warning. I write
for ($x .. $y) { .. }
quite often, knowing that it will not do anything if $y < $x.
@a = 1 .. 3 # 3-element list
@a = 1 .. 2 # 2-element list
@a = 1 .. 1 # 1-element list
@a = 1 .. 0 # 0-element list
The latter to be a 2 element list would be very surprising (and would require a lot of extra code in my programs). | [reply] [d/l] [select] |
Re: the '..' operator and decreasing values
by sh1tn (Priest) on Mar 05, 2005 at 04:20 UTC
|
do{
$_ = 100 unless$_;--$_;
# do something
} while $_
| [reply] [d/l] |
Re: the '..' operator and decreasing values
by deibyz (Hermit) on Mar 07, 2005 at 11:49 UTC
|
I think that the cause of this behaviour is the Mathematical definition of interval.
An interval [ a , b ] is defined as (free definition) "Every number greater than a and lesser than b" (definition). So, if a=2 and b=1, there's no number with such condition. That's a valid definition for every set with a ">" operator, so it could work with any set (class) with ">" defined and a valid "generator" (++) (This last statement is only theory, someone with time to test).
| [reply] [d/l] |
Re: the '..' operator and decreasing values
by TedPride (Priest) on Mar 05, 2005 at 19:22 UTC
|
for (0..10) {
$_ = 10 - $_;
print;
}
| [reply] [d/l] |
Re: the '..' operator and decreasing values
by Woodchuck (Initiate) on Mar 05, 2005 at 21:28 UTC
|
Wouldn't :
foreach my $i (10 .. 0) {
#Do something
}
do the trick instead???
-Woodchuck | [reply] |
|
No, since "for" is simply an alias of "foreach", so that your code is exactly quivalent to the original poster's code.
| [reply] |