Reputation: 627
This is probably a silly question, but this is kinda making me crazy. I have this simple code:
let args = env::args();
println!("num args read: {}", args.len());
for element in args {
println!("{}", element);
}
let arg_string: String = args.collect();
This doesn't work and gives the error:
|
4 | let args = env::args();
| -------- move occurs because `args` has type `std::env::Args`, which does not implement the `Copy` trait
...
8 | for element in args {
| ----
| |
| `args` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&args`
...
14 | let arg_string: String = args.collect();
| ^^^^ value used here after move
This makes sense as the into_iter()
call consumes self
. So I try to modify the for-loop to for element in &args
and I get this error:
9 | for element in &args {
| -^^^^
| |
| `&std::env::Args` is not an iterator
| help: consider removing the leading `&`-reference
|
= help: the trait `std::iter::Iterator` is not implemented for `&std::env::Args`
= note: `std::iter::Iterator` is implemented for `&mut std::env::Args`, but not for `&std::env::Args`
= note: required by `std::iter::IntoIterator::into_iter`
Why can't I iterate over a reference over a iterator? I found out that I can do
let mut args = env::args();
println!("num args read: {}", args.len());
for element in &mut args {
println!("{}", element);
}
let arg_string: String = args.collect();
and this gets rid of the compiler error. Why must I take a mutable reference here instead of just a reference?
Upvotes: 3
Views: 346
Reputation: 60692
You're using Args
like it is a collection, but it isn't; its an iterator. Your &mut
workaround satisfies the compiler but doesn't actually do what you want. The for-loop will exhaust the iterator meaning the args.collect()
won't yield any values.
The fix is to call env::args()
separately for each usage. You aren't saving anything by trying to use the same variable. I forgot that Args
creates owned String
s, so you might be better off collecting the args into a Vec
first if you need to iterate over it multiple times.
Upvotes: 3