A1 - Нет, это не так, как работает слежка.Давайте посмотрим на ваш код с комментариями.
fn gettemp() -> f32 {
let temp = String::new(); // Outer
loop {
// There's no inner temp at this point, even in the second
// loop pass, etc.
println!("What is your temperature?");
// Here temp refers to the outer one (outside of the loop)
io::stdin().read_line(&mut temp).expect("Failed to read the line");
// Shadowed temp = let's call it inner temp
let temp = temp.trim().parse::<f32>();
// ^ ^
// | |- Outer temp
// |- New inner temp
// temp refers to inner temp
if !temp.is_ok() {
println!("Not a number!");
} else {
// Inner temp goes out of scope
break;
}
// Inner temp goes out of scope
}
// Here temp refers to outer one (String)
temp
}
A2 - вы не можете вернуть &str
.@ E_net4 разместил ссылку на ответ почему.Тем не менее, вы можете вернуть String
.Вы можете сделать что-то вроде этого, если вы хотите иметь проверенный String
:
fn gettemp() -> String {
loop {
println!("What is your temperature?");
let mut temp = String::new();
io::stdin()
.read_line(&mut temp)
.expect("Failed to read the line");
let trimmed = temp.trim();
match trimmed.parse::<f32>() {
Ok(_) => return trimmed.to_string(),
Err(_) => println!("Not a number!"),
};
}
}
Я вижу несколько других проблем в вашем коде.
let temp = String::new();
Должно быть let mut temp
, потому что вы хотите заимствовать изменяемую ссылку позже (&mut temp
в вызове read_line
).
Другая проблема - loop
& read_line
.read_line
добавляет к String
.Запустите этот код ...
let mut temp = "foo".to_string();
io::stdin().read_line(&mut temp).unwrap();
println!("->{}<-", temp);
... и, например, введите 10
.Вы увидите следующий вывод ...
->foo10
<-
... это не то, что вы хотите.Я бы переписал gettemp()
следующим образом:
fn gettemp() -> f32 {
loop {
println!("What is your temperature?");
let mut temp = String::new();
io::stdin()
.read_line(&mut temp)
.expect("Failed to read the line");
match temp.trim().parse() {
Ok(temp) => return temp,
Err(_) => println!("Not a number!"),
};
}
}
ИМХО явное return temp
намного чище и удобочитаемее (по сравнению с предлагаемым разрывом цикла со значением).
A3 - Почему нам не нужно явно указывать <f32>
в temp.trim().parse()
Это выводится компилятором.
fn gettemp() -> f32 { // 1. f32 is return type
loop {
println!("What is your temperature?");
let mut temp = String::new();
io::stdin()
.read_line(&mut temp)
.expect("Failed to read the line");
match temp.trim().parse() {
// 4. parse signature is pub fn parse<F>(&self) -> Result<F, ...>
// compiler knows it must be Result<f32, ...>
// Result<f32, ...> = Result<F, ...> => F = f32
// F was inferred and there's no need to explicitly state it
Ok(temp) => return temp,
// | |
// | 2. return type is f32, temp must be f32
// |
// | 3. temp must be f32, the parse result must be Result<f32, ...>
Err(_) => println!("Not a number!"),
};
}
}