#发散函数
发散函数 никогда не возвращают значения. Они помечаются с использованием !
, который является пустым типом.
fn foo() ->! {
panic!("This call never returns.");
}
В отличие от всех других типов, этот тип не может быть инстанциирован, потому что множество всех возможных значений, которое может иметь этот тип, пусто. Обратите внимание, что это отличается от типа ()
, который имеет ровно одно возможное значение.
Например, эта функция возвращает значение, как обычно, хотя в возвращаемом значении нет информации.
fn some_fn() {
()
}
fn main() {
let _a: () = some_fn();
println!("This function returns and you can see this line.");
}
В отличие от этой функции, которая никогда не вернет управление обратно вызывающей стороне.
#![feature(never_type)]
fn main() {
let x:! = panic!("This call never returns.");
println!("You will never see this line!");
}
Хотя это может показаться абстрактной концепцией, на самом деле она очень полезна и часто удобна в использовании. Главное преимущество этого типа заключается в том, что его можно преобразовать в любой другой тип и поэтому использовать в местах, где требуется точный тип, например, в ветках match
. Это позволяет нам писать код такого вида:
fn main() {
fn sum_odd_numbers(up_to: u32) -> u32 {
let mut acc = 0;
for i in 0..up_to {
// Обратите внимание, что тип возврата этого выражения match должен быть u32
// из-за типа переменной "addition".
let addition: u32 = match i%2 == 1 {
// Переменная "i" имеет тип u32, что совершенно нормально.
true => i,
// С другой стороны, выражение "continue" не возвращает
// u32, но это все еще нормально, потому что оно никогда не возвращает и поэтому
// не нарушает требования типов выражения match.
false => continue,
};
acc += addition;
}
acc
}
println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9));
}
Это также тип возврата функций, которые бесконечно циклируют (например, loop {}
), как в случае с сетевыми серверами, или функций, которые завершают процесс (например, exit()
).