How do you make a range in Rust?
Asked Answered
C

7

53

The documentation doesn't say how and the tutorial completely ignores for loops.

Congratulation answered 14/2, 2012 at 5:3 Comment(3)
possible duplicate of In rust, what is the idiomatic equivalent of Haskell's [n..m]?Chlamydospore
Take a look at doc.rust-lang.org/std/ops/struct.RangeFrom.htmlLyautey
This is an old and obsolete question, but you should have provided at least the link to the "tutorial" you were reading. We cannot just guess.Charlottecharlottenburg
M
44

As of 1.0, for loops work with values of types with the Iterator trait.

The book describes this technique in chapter 3.5 and chapter 13.2.

If you are interested in how for loops operate, see the described syntactic sugar in Module std::iter.

Example:

fn main() {
    let strs = ["red", "green", "blue"];

    for sptr in strs.iter() {
        println!("{}", sptr);
    }
}

(Playground)

If you just want to iterate over a range of numbers, as in C's for loops, you can create a numeric range with the a..b syntax:

for i in 0..3 {
    println!("{}", i);
}

If you need both, the index and the element from an array, the idiomatic way to get that is with the Iterator::enumerate method:

fn main() {
    let strs = ["red", "green", "blue"];

    for (i, s) in strs.iter().enumerate() {
        println!("String #{} is {}", i, s);
    }
}

Notes:

  • The loop items are borrowed references to the iteratee elements. In this case, the elements of strs have type &'static str - they are borrowed pointers to static strings. This means sptr has type &&'static str, so we dereference it as *sptr. An alternative form which I prefer is:

      for &s in strs.iter() {
          println!("{}", s);
      }
    
Matty answered 2/10, 2013 at 19:18 Comment(5)
How to make rev for 0..3?Archive
@EvgeniNabokov Add parenthesis: for i in (0..3).rev() { // Code here... } Reference: doc.rust-lang.org/book/ch03-05-control-flow.htmlHolcman
How do I make i a u8? I did for i: u8 in 0..26 { and it is not working.Interlanguage
Why is this not the top answer, despite being the most voted and the accepted answer? SO works in weird ways..Cytogenesis
@Interlanguage for i in 0u8..26u8 (one of the u8s can even be omitted, but that may be confusing for beginners)Inbeing
B
12

for i in range(0, 100) is now deprecated in favour of for i in 0..100 (according to rustc 1.0.0-nightly.

Also worth noting is the compiler can't disambiguate when you use an identifier in the range (e.g., for i in 0..a), so you have to use for i in (0..a), but there's a pull request submitted to fix this.

Birdsall answered 13/1, 2015 at 11:16 Comment(1)
identifier ambiguity has been fixed in github.com/rust-lang/rust/pull/21374Avis
T
10

Actually, the Loops section of the tutorial does cover for loops:

When iterating over a vector, use for instead.

for elt in ["red", "green", "blue"] {
   std::io::println(elt);
}

But if you needed indices, you could do something like the following, using the uint::range function from the core library (or int::range or u8::range or u32::range or u64::range) and Rust's syntax for blocks:

range(0u, 64u, {|i| C[i] = A[i] + B[i]});

Rust used to support this equivalent syntax but it was later removed:

range(0u, 64u) {|i|
    C[i] = A[i] + B[i];
}
Townshend answered 14/2, 2012 at 18:40 Comment(4)
Thanks! I'm curious why Rust has two different syntaxes for function definitions and blocks. Seems like they could save the coder trouble by reusing fn(args...) instead of |args|.Congratulation
@Congratulation Actually, the Ruby-style block syntax {|args| body} is used to denote a closure rather than just a function. It's also really convenient for simplifying usage of anonymous functions as you might see them used in Javascript, since any function that accepts a closure as its last argument (such as a callback) can be written after the function call, as in Lindsey's third example above. Finally, even though Rust has a few different types of closures, Rust can infer the type of closure you want when using the block syntax. See also doc.rust-lang.org/doc/tutorial.html#closuresBuie
Does this still work? I can't get range(n,n) {|i| ...} to compile. I get weird errors.Nosography
As of rust 0.6, for int::range() |i| { C[i] = A[i] + B[i]; } should work. for is syntactic sugar which passes the closure in as an argument, iirc.Anglonorman
P
6
let range = (start..end).collect::<Vec<i32>>();
Protozoal answered 27/12, 2021 at 12:36 Comment(1)
Do you know why the decision was made to support FromIterator<usize> for Vec<i32> but not Vec<i64>? Would love to use this syntax but i64 is so common...Istic
N
0

Note that as of rustc 0.4 (Oct 2012), the alternate construction of

range(0u, 64u) {|i|
    C[i] = A[i] + B[i];
}

appears to not be supported any more.

Noletta answered 31/10, 2012 at 18:37 Comment(0)
B
0

range in fn:

fn print_range(range: std::ops::Range<i32>) {
    for num in range {
        println!("{}", num);
    }
}

fn main() {
    let my_range = 1..=5;
    print_range(my_range);
}
Bridget answered 4/4 at 13:17 Comment(0)
C
-4

Use int::range.

Congratulation answered 14/2, 2012 at 5:5 Comment(2)
if there was an int type, it has been deprecated now.Beneath
He's right. It has been removed so this answer is obsolete.Skidmore

© 2022 - 2024 — McMap. All rights reserved.