The iterator method take_while
takes as its argument a closure.
For example:
fn main() {
let s = "hello!";
let iter = s.chars();
let s2 = iter.take_while(|x| *x != 'o').collect::<String>();
// ^^^^^^^^^^^^^
// closure
println!("{}", s2); // hell
}
This is fine for simple closures, but if I want a more complicated predicate, I don't want to write it directly in the take_while
argument. Rather, I would like to return the closure from a function.
I seem to be having trouble getting this to work. Here is my naive attempt:
fn clos(a: char) -> Box<Fn(char) -> bool> {
Box::new(move |b| a != b)
}
fn main() {
// println!("{}", clos('a')('b')); // <-- true
// ^--- Using the closure here is fine
let s = "hello!";
let mut iter = s.chars();
let s2 = iter.take_while( clos('o') ).collect::<String>();
// ^--- This causes lots of issues
println!("{}", s2);
}
However, the error that it causes has proven difficult to understand:
error[E0277]: the trait bound `for<'r> Box<std::ops::Fn(char) -> bool>: std::ops::FnMut<(&'r char,)>` is not satisfied
--> <anon>:11:23
|
11 | let s2 = iter.take_while( clos('o') ).collect::<String>();
| ^^^^^^^^^^ trait `for<'r> Box<std::ops::Fn(char) -> bool>: std::ops::FnMut<(&'r char,)>` not satisfied
error[E0277]: the trait bound `for<'r> Box<std::ops::Fn(char) -> bool>: std::ops::FnOnce<(&'r char,)>` is not satisfied
--> <anon>:11:23
|
11 | let s2 = iter.take_while( clos('o') ).collect::<String>();
| ^^^^^^^^^^ trait `for<'r> Box<std::ops::Fn(char) -> bool>: std::ops::FnOnce<(&'r char,)>` not satisfied
|
= help: the following implementations were found:
= help: <Box<std::boxed::FnBox<A, Output=R> + 'a> as std::ops::FnOnce<A>>
= help: <Box<std::boxed::FnBox<A, Output=R> + Send + 'a> as std::ops::FnOnce<A>>
error: no method named `collect` found for type `std::iter::TakeWhile<std::str::Chars<'_>, Box<std::ops::Fn(char) -> bool>>` in the current scope
--> <anon>:11:47
|
11 | let s2 = iter.take_while( clos('o') ).collect::<String>();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied: `Box<std::ops::Fn(char) -> bool> : std::ops::FnMut<(&char,)>`, `std::iter::TakeWhile<std::str::Chars<'_>, Box<std::ops::Fn(char) -> bool>> : std::iter::Iterator`
error: aborting due to 3 previous errors
I have tried some other things, including using FnBox
, but it didn't work. I haven't used closures that much, so I'd really like to understand what is going wrong, as well as how to fix it.