Можно ли объявить тип переменной в Rust для циклов?

C++ пример:

for (long i = 0; i < 101; i++) {
    //...
}

В Rust я попробовал:

for i: i64 in 1..100 {
    // ...
}

Я мог бы просто объявить let i: i64 = var перед циклом for, но я бы лучше изучил правильный способ сделать это, но это привело к

error: expected one of `@` or `in`, found `:`
 --> src/main.rs:2:10
  |
2 |     for i: i64 in 1..100 {
  |          ^ expected one of `@` or `in` here

5 ответов

Решение

Вы можете использовать целочисленный суффикс для одного из литералов, которые вы использовали в диапазоне. Вывод типа сделает все остальное:

for i in 1i64..101 {
    println!("{}", i);
}

Нет, невозможно объявить тип переменной в for петля.

Вместо этого, более общий подход (например, применим также к enumerate()) представляет let связывание путем разрушения элемента внутри тела цикла.

Пример:

for e in bytes.iter().enumerate() {
    let (i, &item): (usize, &u8) = e; // here
    if item == b' ' {
        return i;
    }
}

Если ваша переменная цикла является результатом вызова функции, которая возвращает универсальный тип:

let input = ["1", "two", "3"];
for v in input.iter().map(|x| x.parse()) {
    println!("{:?}", v);
}
error[E0284]: type annotations required: cannot resolve `<_ as std::str::FromStr>::Err == _`
 --> src/main.rs:3:37
  |
3 |     for v in input.iter().map(|x| x.parse()) {
  |                                     ^^^^^

Вы можете использовать турбовину, чтобы указать типы:

for v in input.iter().map(|x| x.parse::<i32>()) {
//                                   ^^^^^^^
    println!("{:?}", v);
}

Или вы можете использовать полный синтаксис:

for v in input.iter().map(|x| <i32 as std::str::FromStr>::from_str(x)) {
//                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    println!("{:?}", v);
}

Смотрите также:

Попробуйте использовать as:

      for i in 1..100 as i64 {
    // ...
}

Раньше было обсуждение , где это требовалось, за которым последовал фактический RFC.

Однако похоже, что дискуссия была отложена, потому что мало кто действительно интересовался этой темой.

В настоящее время, если вы абсолютно хотите аннотировать, кажется, что лучший вариант, который у вас есть, это:

      fn main() {
    let my_vec: Vec<i32> = vec![-1, 22, -333];
    for i in my_vec.iter() {
        let _: &i32 = i;
        println!("{}", i);
    }
}

Как видите, это не работает, если тип не совпадает:

      fn main() {
    let my_vec: Vec<i32> = vec![-1, 22, -333];
    for i in my_vec.iter() {
        let _: &i16 = i;
        println!("{}", i);
    }
}
       --> src/main.rs:4:23
  |
4 |         let _: &i16 = i;
  |                ----   ^ expected `i16`, found `i32`
  |                |
  |                expected due to this
  |
  = note: expected reference `&i16`
             found reference `&i32`

Конечно, из-за автоматического разыменования этот метод не может различать&i32и&&i32, что может быть проблемой в некоторых случаях:

      fn main() {
    let my_vec: Vec<i32> = vec![-1, 22, -333];
    for i in my_vec.iter() {
        let _: &i32 = &i; // Compiles, but the right side is &&i32
        println!("{}", i);
    }
}

Но в целом, на мой взгляд, это должно внушать доверие потенциальным рецензентам.

Другие вопросы по тегам