У меня есть функция, которая принимает ссылку на перечисление, которое мне нужно проанализировать путем сопоставления перечисления и чтения его содержимого.Один из вариантов перечисления (не в упрощенном минимальном рабочем примере ниже) может содержать в качестве значения тип самого перечисления, поэтому мне может потребоваться рекурсивный вызов той же самой функции для анализа ее значения.
Я хотел бы написать функцию, которая действует как фильтр и возвращает Option::Some
, содержащий ссылку на содержимое варианта enum, или None
, если значение должно быть отброшено.
Далее следуетминимальный рабочий (не совсем компилируемый) пример:
enum Data<'a> {
Value(&'a String),
Null,
}
fn main() {
let s = String::new();
let d = Data::Value(&s);
let equal = |d: &Data| -> Option<&String> {
if let Data::Value(s) = d {
Some(s)
} else {
None
}
};
parse(&d, equal);
//parse(&d, equal_filter);
}
fn equal_filter<'a>(d: &'a Data) -> Option<&'a String> {
if let Data::Value(s) = d {
Some(s)
} else {
None
}
}
fn parse<'a, F>(data: &Data<'a>, filter: F)
where
F: Fn(&Data<'a>) -> Option<&'a String>,
{
filter(data);
}
Playground .
Сначала я попытался скомпилировать код с помощью замыкания, но в этом случае я получаю ошибку:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:11:33
|
11 | if let Data::Value(s) = d {
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 10:17...
--> src/main.rs:10:17
|
10 | let equal = |d: &Data| -> Option<&String> {
| _________________^
11 | | if let Data::Value(s) = d {
12 | | Some(s)
13 | | } else {
14 | | None
15 | | }
16 | | };
| |_____^
= note: ...so that the types are compatible:
expected &Data<'_>
found &Data<'_>
note: but, the lifetime must be valid for the expression at 18:5...
--> src/main.rs:18:5
|
18 | parse(&d, equal);
| ^^^^^
note: ...so that a type/lifetime parameter is in scope here
--> src/main.rs:18:5
|
18 | parse(&d, equal);
| ^^^^^
Итак, я попытался с функцией, но получил другую ошибку:
error[E0271]: type mismatch resolving `for<'r> <for<'a, 's> fn(&'a Data<'s>) -> std::option::Option<&'a std::string::String> {equal_filter} as std::ops::FnOnce<(&'r Data<'_>,)>>::Output == std::option::Option<&std::string::String>`
--> src/main.rs:19:5
|
19 | parse(&d, equal_filter);
| ^^^^^ expected bound lifetime parameter, found concrete lifetime
|
note: required by `parse`
--> src/main.rs:30:1
|
30 | / fn parse<'a, F>(data: &Data<'a>, filter: F)
31 | | where
32 | | F: Fn(&Data<'a>) -> Option<&'a String>,
33 | | {
34 | | filter(data);
35 | | }
| |_^
Я бы предпочел решить проблему с помощьюзакрытие, но я не знаю, как поступить, даже используя функцию.