Reputation: 4698
I have written the following nom parser code:
use nom::character::complete::digit1;
use nom::combinator::map_res;
use nom::error::Error;
use nom::sequence::tuple;
use nom::Err;
type E<'a> = Err<Error<&'a str>>;
fn parse_double_int(input: &str) -> Option<(i32, i32)> {
let num = map_res(digit1, |s: &str| s.parse::<i32>());
let mut pair = tuple((num, num));
let res: Result<_, E> = pair(&input.trim());
match res {
Ok((_, (a, b))) => Some((a, b)),
Err(_) => None,
}
}
Error:
error[E0382]: use of moved value: `num`
--> src\lib.rs:11:32
|
10 | let num = map_res(digit1, |s: &str| s.parse::<i32>());
| --- move occurs because `num` has type `impl FnMut<(&str,)>`, which does not implement the `Copy` trait
11 | let mut pair = tuple((num, num));
| --- ^^^ value used here after move
| |
| value moved here
For more information about this error, try `rustc --explain E0382`.
How can I reuse the parsers I have defined locally?
Upvotes: 1
Views: 529
Reputation: 26717
map_res
return a FnMut
. You can't move twice a FnMut
cause FnMut
doesn't implement Copy
, than the obvious solution would be to borrow it, but you can't cause Parser
require mut
and you can't have multiple mutable borrow. So the last option is to implement a Parser
that either implement Copy
or can be create easily:
wrap the FnMut
inside a Fn
closure that Implement copy:
let num = |input| map_res(digit1, |s: &str| s.parse::<i32>())(input);
Create a function:
fn num(input: &str) -> IResult<&str, i32> {
map_res(digit1, |s: &str| s.parse::<i32>())(input)
}
Upvotes: 3
Reputation: 281
You are "moving the value" meaning that Rust is giving ownership of your value num and then freeing it (deleting it) when it is finished, you can try letting your function borrow the value with the &num notation, or cloning the variable if the struct implements the clone trait. There is a similar problem here I can't recreate your problem with just the snippet but hopefully this gives you enough information to find the solution!
Upvotes: 2