Reputation: 349
I am trying to send the result of a match to a function Foo
, but the result of the match is type Some()
How can I send it as an argument to the Foo
function?
struct Person {
name: Option<String>,
lastname: Option<String>,
}
fn Foo(x: Option<String>) {
println!("{:?}", x);
}
fn main() {
let name = "Steve".to_string();
let lastname = "Alvarez".to_string();
let mut x: Option<Person> = Some(Person {
name: Some(name),
lastname: Some(lastname),
});
match x {
Some(Person {
name: ref a @ Some(_),
lastname: ref b @ _,
}) => Foo(a),
_ => {}
}
}
Upvotes: 0
Views: 225
Reputation: 73570
I think the problem with the existing code is that Foo
consumes an Option
, while your match gets a reference to an Option
. They need to match. There's a few approaches that will work here.
Foo
and the match both use values. This means you remove the ref
on the match pieces. You wont be able to use the Person
value after the match, since it will have been chopped into its component pieces.fn Foo(x: Option<String>) {
println!("{:?}", x);
}
// ...
match x {
Some(Person {
name: a @ Some(_),
lastname: b @ _,
}) => Foo(a),
_ => {}
}
Foo
and the match both use references. You keep the ref on the match, but add an &
to Foo
's argument.fn Foo(x: &Option<String>) {
println!("{:?}", x);
}
// ...
match x {
Some(Person {
name: ref a @ Some(_),
lastname: ref b @ _,
}) => Foo(a),
_ => {}
}
a
before passing it to Foo
. Foo
and the match pattern don't change, but the way you call Foo
changes slightlyfn Foo(x: Option<String>) {
println!("{:?}", x);
}
// ...
match x {
Some(Person {
name: ref a @ Some(_),
lastname: ref b @ _,
}) => Foo(a.clone()),
_ => {}
}
Of course, in your particular case you dont need to use pattern matching at all, you could just use some of the tools that already exist in Option
, such as map
.
x.map(|p| Foo(p.name));
Upvotes: 0
Reputation: 16217
First, your match x { Some(Person{...})...
looks wrong. Unwrap it as Some(person) => foo(person.name)
.
struct Person {
name: Option<String>,
lastname: Option<String>,
}
fn foo(x: Option<String>) {
println!("{:?}", x);
}
fn main() {
let name = "Steve".to_string();
let lastname = "Alvarez".to_string();
let x: Option<Person> = Some(Person {
name: Some(name),
lastname: Some(lastname),
});
match x {
Some(person) => foo(person.name),
_ => {}
}
}
Taking an Option
as a function argument is not very Rust-like, I believe. (I might be wrong, since I am new to Rust as well.)
Also, the match
where the None
option is not taken is also an antipattern, I believe. Instead, use a combinator (map
or and_then
).
struct Person {
name: Option<String>,
lastname: Option<String>,
}
fn foo(x: String) {
println!("{:}", x);
}
fn main() {
let name = "Steve".to_string();
let lastname = "Alvarez".to_string();
let x: Option<Person> = Some(Person {
name: Some(name),
lastname: Some(lastname),
});
x.and_then(|person| person.name) // person.name is an Option -> thus use `and_then`
.map(|n| foo(n));
}
Upvotes: 2