Проблема арифметического порядка операций с диапазоном - PullRequest
0 голосов
/ 02 января 2019

Я пытаюсь изучать Rust, используя книгу Rust и сайт Exercism.io.У меня проблема с этим конкретным упражнением .Код выглядит следующим образом:

pub fn series(_digits: &str, _len: usize) -> Vec<String> {
    (0.._digits.len() + 1 - _len)
        .map(|i| _digits[i..i + _len].to_string())
        .collect()
}

Например, series("12345", 3) должен возвращать Vec, содержащий ["123", "234", "345"].

Вместо (0.._digits.len() + 1 - _len), я экспериментировал с использованием (0.._digits.len() - _len + 1)вместо этого, но в этом случае, модульный тест "test_too_long" не проходит:

#[test]
#[ignore]
fn test_too_long() {
    let expected: Vec<String> = vec![];
    assert_eq!(series("92017", 6), expected);
}

Я удивлен, потому что, похоже, он для меня такой же.Почему это не удалось?

1 Ответ

0 голосов
/ 02 января 2019

Это происходит потому, что в режиме отладки арифметические операции, которые переполняются, вместо паники и паники приводят к сбою тестов.

В переставленной версии ( детская площадка ), в series("12345", 6),digits.len() - len + 1 становится 5usize - 6usize + 1usize.Программа даже не доходит до + 1, потому что просто 5usize - 6usize паникует.(usize не может представлять отрицательные числа, поэтому вычитание 6 из 5 приводит к переполнению.)

Сообщение об ошибке содержит строгую подсказку о характере ошибки:

---- test_too_long stdout ----
thread 'test_too_long' panicked at 'attempt to subtract with overflow', src/lib.rs:2:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

digits.len() + 1 - len работает, однако, потому что 6 равен в точности на единицу больше, чем длина строки, и поэтому 5 + 1 - 6 может обнуляться без переполнения.Но если вы измените test_too_long на series("12345", 7), обе версии будут паниковать.Это похоже на упущение со стороны тех, кто написал набор тестов, особенно учитывая, что в инструкциях не указано ожидаемое поведение:

И если вы просите 6-значный ряд из 5-значная строка, вы заслуживаете все, что получаете.

Для чего стоит, вот один из способов заставить series возвращать пустой вектор для любого len, большего, чем длина ввода: (digits.len() + 1).saturating_sub(len) похоже на digits.len() + 1 - len, но если результат вычитания будет меньше 0, он просто возвращает 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...