Use of for loop with named range constant

After reading the official Rust book, I plan to convert my tiny Nim chess game to Rust over Christmas holiday. The chess game uses many named range constants with for loops. In Nim we can write

# named range example

const Launch = 1 .. 9

proc main =
  
  for t in Launch:
    echo t
  echo "Go!"
  
main()

which prints the numbers 1 to 9 and finally "Go!".

I did some google search and asked GPT-4. Its explanations seems to make some sense, and it suggests in https://chat.openai.com/share/483ce4ee-f62e-45f1-bdfc-af456f1876af

// Named range equivalent in Rust

const LAUNCH: (i32, i32) = (1, 10); // In Rust, the end of the range is exclusive

fn main() {
    for t in LAUNCH.0..LAUNCH.1 {
        println!("{}", t);
    }
    println!("Go!");
}

or

const LAUNCH_START: i32 = 1;
const LAUNCH_END: i32 = 10; // Exclusive

fn main() {
    for t in LAUNCH_START..LAUNCH_END {
        println!("{}", t);
    }
    println!("Go!");
}

Which variant should I use?

You can use named ranges in Rust as well:

use core::ops::Range;

const LAUNCH: Range<i32> = 1..10;

fn main() {
    for i in LAUNCH {
        println!("{}", i);
    }
}
5 Likes

My inclination would be to write something like this:

fn launch_count()->impl Iterator<Item=i32> {
    (1..=10).rev()
}

fn main() {
    for t in launch_count() {
        println!("{}", t);
    }
    println!("Go!");
}
4 Likes

Great. I was indeed looking for such a simple solution, but was not able to find it in the book, or other resources. Actually I tried something similar, but I guess I used an invalid syntax. Would the solution from 2e71828 with the explicit iterator offer some extra benefit?

Well if you need the .rev() then you have to do it like @2e71828, because a std::iter::Rev cannot be constant initialized, meaning you can't use it in a const context.

And maybe it is a bit more clear in @2e71828 's version that you get a new Iterator each time you call the function. At least for me it wasn't immediatly clear what would happen with the constant.

4 Likes

Actually, this works as well for an inverted range:

const LAUNCH: core::ops::Range<i32> = 1..10;

fn main() {
    for i in LAUNCH.rev() {
        println!("{}", i);
    }
}

Yeah ok, but the const is not inverted. For a more complicated iterator construction this would not be feasible anymore.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.