Чтобы изучить Rust, я пишу библиотеку комбинаторов парсеров. Теперь у меня проблема, связанная со сложным типом среза и владением. У меня есть несколько функций строительных блоков, которые я хотел бы использовать отдельно:
pub fn achar(character: char) -> impl Fn(&str) -> Option<char> {
move |input| match input.chars().next() {
Some(c) if c == character => Some(c),
_ => None,
}
}
pub fn alternatives<'a, T>(
alts: &'a [impl Fn(&'a str) -> Option<T>],
) -> impl Fn(&'a str) -> Option<T> {
move |input| {
for alt in alts.iter() {
let tried = alt(input);
if tried.is_none() {
continue;
}
return tried;
}
None
}
}
pub fn one_of<'a>(allowed: &'a str) -> impl Fn(&'a str) -> Option<char> {
let v = allowed.chars().map(achar).collect::<Vec<_>>();
alternatives(&v)
}
Тогда использование будет выглядеть так:
fn main() {
println!("{:?}", achar('f')("foo"));
println!("{:?}", alternatives(vec![achar('f'), achar('b')])("foo"));
println!("{:?}", one_of("foo")("foo"));
}
Вот так я получаю следующую ошибку:
= note: expected type `for<'r> fn(&'r str) -> std::option::Option<char> {any_char}`
found reference `&impl for<'r> std::ops::Fn<(&'r str,)>`
Я бы сказал, что quote
реализует Fn(&str)
, не так ли? Как я могу заставить это работать?
Как только это будет решено, появится следующая проблема:
33 | alternatives(&v) | ^^^^^^^^^^^^^--^ | | | | | `v` is borrowed here | returns a value referencing data owned by the current function
Конечно, встраивание не решает проблемы. Я понятия не имею, как можно атаковать это.