Reputation: 529
I am new to Rust, and it seems very awkward to use sequences of functional transformations on strings, because they often return &str
.
For example, here is an implementation in which I try to read lines of two words separated by a space, and store them into a container of tuples:
use itertools::Itertools;
fn main() {
let s = std::io::stdin()
.lines()
.map(|l| l.unwrap())
.map(|l| {
l.split(" ")
.collect_tuple()
.map(|(a, b)| (a.to_string(), b.to_string()))
.unwrap()
})
.collect::<Vec<_>>();
println!("{:?}", s);
}
Because split
returns an iterator to &str
objects, whose scope is the lambda used for the map
, the only way I saw to return them was to manually convert them back to string
s. This seems really awkward.
Is there a better way to implement such a program?
Upvotes: 0
Views: 1242
Reputation: 71919
Rust is explicit about allocation. The String
s returned by the lines()
iterator don't persist beyond the iterator chain, so you can't just store references into them. Therefore, logically, there needs to be a to_string()
(or to_owned
, or String::from
) somewhere.
But putting it after the tuple creation is a bit awkward, because it requires you to call the function twice. You can turn the result of the split()
into owned objects instead. This should work:
.map(|l| {
l.split(" ")
.map(String::from)
.collect_tuple()
.unwrap()
})
.collect::<Vec<(_,_)>>();
Note that now you have to be explicit about the tuple type, though.
Upvotes: 4