Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a Range with .., but counting down

Tags:

raku

I want to have a loop that counts from 5 to 1. I know I can do the opposite easily with the .. operator:

for 1..5 { .print }
12345

But when using the .. operator and reversing the sides, it doesn't seem to generate a valid Range that for can work with:

for 5..1 { .print }
Nil

I know I can use the reverse method on the Range object:

for (1..5).reverse { .print }
54321

However, I would expect that the .. operator has a certain way to generate the list of numbers in 1 call. My question is, how to create a Range that counts down using the .. operator?

like image 318
Tyil Avatar asked Sep 24 '18 16:09

Tyil


1 Answers

Just use 5...1 (note the 3 ... ):

for 5...1 { .print }
54321

The iterator that Range.reverse is basically the same iterator as for forwards, but iterating from the end to the beginning. Apart from the extra initial call to .reverse, there should be no difference in execution.

Except for the fact that for 1..5 { } is actually statically optimized to not use a Range internally at all. I guess this is an opportunity for a further statical optimization.

EDIT: https://github.com/rakudo/rakudo/commit/2dd02751da ensures that for (1..5).reverse is optimized in the same way as for 1..5. This makes it about 6x faster.

EDIT: As of https://github.com/rakudo/rakudo/commit/dfd6450d74 , the best way to count down a Range is for 5...1: this uses the same optimization as (1..5).reverse, but is much more readable.

like image 143
Elizabeth Mattijsen Avatar answered Dec 20 '22 06:12

Elizabeth Mattijsen