I am trying to access the description option using the following:
let desc = match d.desc {
Some(desc) => desc,
None => (), // I have tried multiple things here
}
I get:
error: match arms have incompatible types:
expected `collections::string::String`,
found `()` // or whatever else I put in there
What am I doing wrong here and what's the good thing to do here? I am trying to loop over a list of devices and print their names and descriptions. In some cases description is None. What is the rust way to deal with that?
The problem is that depending on presence of desc, you are returning either desc which is string, or () - that's what rust complain about. You choice is to either:
Embrace the fact that there is no value in some cases and pass it higher. In that case there is no point of pattern matching here.
Yes, using the various Option methods instead of pattern-matching is considered idiomatic. Although you should use to_owned() or into() instead of to_string().
There is no reason it shouldn't. You haven't shown your latest code with match, there must have been a typo somewhere.
let _desc = match d.desc {
Some(desc) => desc,
None => "".to_string(),
};
Note the ; which ends the expression.
I would guess you did:
match d.desc {
Some(desc) => desc,
None => "".to_string(),
}
Note that you don't associate what is returned from the match arms(no let before the match), so this would go to your function as a return type. You probably tried this in main or other function that returns -> () which would explain why you got that error. The function tried to return that String you told it to return but the function does not return -> String, it expects -> ().
Now, why None => (), doesn't work? Because Some(desc) => desc returns a String and let desc can't understand, should this desc be of type String or of type ()(let desc: String = or let desc: () =)?
Both arms should return the same type, so let desc can deduce the type that match returns.
Why None => "", doesn't work? Because "" is a statically allocated string that would be placed in your data segment of the application and its type is &'static str, which means that it is a reference to a statically allocated string. At runtime it just references that string placed in your data segment. String is a dynamically allocated string. Some(desc) => desc, returns a String, so you are left to make None => "", also return a String, so let desc = gets the same type returned from the match. "".to_string() would return a String out of the statically allocated string.
This is the correct way. Alternatively, you can use Deref::deref or |v| &**v or |v| v.as_ref() - all of these should convert &String to &str. When type ascriptions land, I think it will also be possible to write something like |v| v: &str.
I also find this quite unfortunate and in one of my libraries I even wrote an extension trait for Option<&T> which yields Option<&U> where U is whatever T derefs to. I've removed this bit some time after, though, because I finally discarded options altogether.