I realize Rust is in flux, but I'm trying to learn it anyway. I'm trying to understand how I would adapt the following example, which works with 0.9, into something similar that works with 0.10:
fn main() {
let argv = std::os::args();
let (first, last) = match argv {
[_, first_arg, .., last_arg] => (first_arg, last_arg),
_ => fail!("Error: At least two arguments expected.")
};
println!("The first argument was {:s}, \
and the last argument was {:s}.", first, last);
}
When I build this with 0.10, I get the following error:
error: couldn't read test.rc: no such file or directory (No such file or directory)
orflongpmacx8:rust pohl_longsine$ rustc test.rs
test.rs:9:9: 9:37 error: unique vector patterns are no longer supported
test.rs:9 [_, first_arg, .., last_arg] => (first_arg, last_arg),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
My question: is it still possible to use pattern matching on argv, but with different syntax, or is using a match statement on argv no longer possible at all? If it's the former, what would I have to change?
You can still match on slices &[T]
and fixed length arrays [T, .. n]
. so, in this case,
fn main() {
let argv = std::os::args();
let (first, last) = match argv.as_slice() {
[_, ref first_arg, .., ref last_arg] => (first_arg, last_arg),
_ => fail!("Error: At least two arguments expected.")
};
println!("The first argument was {:s}, \
and the last argument was {:s}.", *first, *last);
}
Note the addition of the ref
s. argv
is ~[~str]
, i.e. the contents are owned strings ~str
, which move ownership when passed by value as a [_, first_arg, .., last_arg]
pattern would do. It's illegal to move ownership out from behind a borrowed pointer (like a slice &[~str]
) so that pattern would be illegal. One can borrow into the slice (and any other pattern) using the ref
keyword, making first
and last
both references of type &~str
.
One might wonder why the *first
and *last
dereferences aren't trying to move a ~str
out from behind a &~str
, but it's because the println!
macro is expanding to essentially &*first
and &*last
, which is fine.
(We could also write => (first_arg.as_slice(), last_arg.as_slice())
to borrow the two &~str
s straight to string slices &str
, which then means we don't need to dereference in the println!
.)