Разделение того, как вычитание диапазона из целого числа работает в Rust

Листинг в Главе 13-04 Rust Book содержит следующий цикл for:

for i in 12..buffer.len() {
    let prediction = coefficients
        .iter()
        .zip(&buffer[i - 12..i])
        .map(|(&c, &s)| c * s as i64)
        .sum::<i64>()
}

Я понимаю, что это делает, за исключением бита «i - 12..i». Я не знал, что можно вычесть диапазон из целого числа и получить... другой диапазон?

Я использовал Rust Playground, чтобы увидеть, как этот синтаксис работает эмпирически:

println!("\"3 - 3..4\": {:?}", 3 - 3..4);
println!("\"3 - 3..3\": {:?}", 3 - 3..3);
println!("\"3 - 3..2\": {:?}", 3 - 3..2);
println!("\"3 - 3..1\": {:?}", 3 - 3..1);
println!("\"3 - 3..0\": {:?}", 3 - 3..0);

Что печатает:

"3 - 3..4": 0..4
"3 - 3..3": 0..3
"3 - 3..2": 0..2
"3 - 3..1": 0..1
"3 - 3..0": 0..0

Следовательно, наивным ответом будет то, что вычитание диапазона из целого числа даст диапазон, который начинается с нуля и заканчивается разницей между целым числом и длиной (положительной или отрицательной) диапазона.

Это хорошее объяснение? Какая черта в std::ops::Range делает возможным этот синтаксис?

Просто совет: вы можете использовать макрос dbg!(...), чтобы избежать повторения. Например. dbg!(3 - 3..4) который выводит: 3 - 3..4 = 0..4

Binier 10.12.2020 14:32

О, приятно знать

Paul Razvan Berg 10.12.2020 14:41
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
2
336
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это связано с приоритетом операторов, который определяет, какие операторы связываются сильнее, чем другие, когда отсутствуют скобки, т. е. если вы пишете a + b * c, интерпретируется ли это как (a + b) * c или a + (b * c).

В этом случае вы просто используете минус и диапазон, но вопрос тот же, так a - b..c интерпретируется как (a - b)..c или a - (b..c)? Это бывший. Поэтому, когда вы пишете 3 - 3..4, это интерпретируется как (3 - 3)..4, поэтому в результате получается диапазон, идущий от 0..4.


Если вы попытаетесь явно заключить диапазон в круглые скобки, например 3 - (3..4), то компилятор выдаст ошибку, говоря, что Sub<Range<{integer}>> for {integer} на самом деле вообще не реализован.

Если вы сомневаетесь, заключите операцию в круглые скобки.

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