Как в замыкании обрабатывать ошибку на примере кода?
Как правильно поправить код, чтобы уйти от ошибки:
'a', 'b' -- is borrowed here
returns a value referencing data owned by the current function
?
use std::collections::HashMap;
#[derive(Debug)]
struct Error;
fn f1(s: &str) -> Result<&str, Error> {
// something for test:
if s.len() > 5 {
Ok(s)
}else{
Err(Error)
}
}
fn f2(s: &str) -> Result<&str, Error> {
todo!()
}
fn r(raw: HashMap<String, String>) -> Result<HashMap<&'static str, &'static str>, Error> {
raw
.into_iter()
.map(|(a, b)| {
// println!("{:?} - {:?}", a, b);
Ok((
f1(&a)?,
f2(&b)?,
))
})
.collect()
}
fn main() {
let raw: HashMap<String, String> = HashMap::from([
("Mercury".to_string(), "0.4".to_string()),
("Venus".to_string(), "0.7".to_string()),
("Earth".to_string(), "1.0".to_string()),
("Mars".to_string(), "1.5".to_string()),
]);
println!("{:?}", r(raw));
}
Ответы (1 шт):
Если компилятор предлагает использовать лайфтайм 'static
, значит велика вероятность, что вы делаете что-то неправильно, а он просто не нашел лучшего предложения по исправлению ошибки.
Здесь ситуация во многом схожая с вот такой, достаточно очевидной ошибкой
fn f(x: i32) -> &i32 {
&x
}
Даже не считая того, что мы пытаемся вернуть ссылку на локальную переменную, проблема возникает в выводе времени жизни результата в сигнатуре функции. Если бы аргумент функции так же был бы передан по ссылке, то, согласно правилам lifetime elision, компилятор использовал бы время жизни этой ссылки и для результата. В данном же случае требуется указать время жизни явно, и единственный известный ему подходящий вариант – 'static
, но он честно признается, что вряд ли это то, что вам нужно.
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
1 | fn f(x: i32) -> &'static i32 {
Правда, для этого простого примера он также предложит более логичный вариант
help: instead, you are more likely to want to change the argument to be borrowed...
|
1 | fn f(x: &i32) -> &i32 {
даже два
help: ...or alternatively, you might want to return an owned value
|
1 - fn f(x: i32) -> &i32 {
1 + fn f(x: i32) -> i32 {
И даже в более сложных случаях
fn f(x: Option<i32>) -> Option<&i32> {
x.as_ref()
}
сможет предложить адекватное решение
1 | fn f(x: &Option<i32>) -> Option<&i32> {
| +
Но он тоже не всесилен, и здесь уже ограничится только предложением со 'static
fn f(x: i32) -> (&i32, &i32) {
(&x, &x)
}
Дублирую исправленный код из комментария к вопросу
use std::collections::HashMap;
#[derive(Debug)]
struct Error;
fn f1(s: &str) -> Result<&str, Error> {
// for test:
if s.len() > 5 {
Ok(s)
}else{
Err(Error)
}
}
fn f2(s: &str) -> Result<&str, Error> {
todo!()
}
fn r(raw: &HashMap<String, String>) -> Result<HashMap<&str, &str>, Error> {
raw
.into_iter()
.map(|(a, b)| {
// println!("{:?} - {:?}", a, b);
Ok((
f1(&a)?,
f2(&b)?,
))
})
.collect()
}
fn main() {
let raw: HashMap<String, String> = HashMap::from([
("Mercury".to_string(), "0.4".to_string()),
("Venus".to_string(), "0.7".to_string()),
("Earth".to_string(), "1.0".to_string()),
("Mars".to_string(), "1.5".to_string()),
]);
println!("{:?}", r(&raw));
}