In the last two years, I sometimes saw functions having the return type Option<Vec>. I know that Rust is proud to have the option type, and often its use makes sense. But when the return type is a vector, it can be empty, which is in principle already some form of NONE. So why put an Option on top?
It depends on how you model your domain. If you need to differentiate an empty vector from an abscence of a value, using Option<Vec>> is what you should use.
Yes, but I can currently not imagine a concrete example. I saw that for an old example using
Similar concept: why use Option<String> when a string can be empty? The case with a string seems more obvious, like of course an empty string is different from None. It's the same for the vec case. But for whatever reason most people don't take any issue when doing it with strings, but for vecs they don't like it.
Really it just depends on what you're trying to communicate from the type signature. Either is fine.
For a string it is easier to see the benefit of an option type, as an empty string can be different from nothing at all. For a vector, we can have the empty vector, or a vector with an empty string. So it is not that clear why we need Option. Of course, the Option does not really hurd, but I got the feeling that either people used it carelessly, or just to show that they know the Option type and are able to use it ![]()
There are interesting answers to your previous thread about it over here Use of Option Types for strings recommended? as well
Exactly my point. For whatever reason, no one really has a problem with Option<String>, even though a string is really just Vec<u8> in a trench coat. Do you want to distinguish between empty and nothing? Then use an option. Otherwise don't.
Oh, I completely forget about that one -- sorry and thanks.
Here is an example: Vec<Vec<String>>::pop() returns Option<Vec<String>>. It would make no sense for it to return an empty Vec<String> if there is nothing to pop.
Great example, thanks. I will bookmark it, so that I will not again forget it.
I think it's easier with Option<String>, which has the equivalent distinction between None vs Some("").
Take Option<String> -> Result<Option<i32>, _>, for example. The behaviour is clear, where None => Ok(None) and Some("") => Err(…).
If you pass in just String instead, you've lost that useful distinction and it's now unclear what should happen with "": is it successfully nothing or a failure because it's not a i32?
Another common case is caches. If you lookup a Vec<String> in a cache, you want the distinction between None (it's not in the cache) and Some([]) (it's in the cache, but the value is empty).
For survey_favorite_foods: Option<Vec<Food>>,
survey_favorite_foods: None
clearly means we did not ask the question, the user opted-out, ..., but
survey_favorite_foods: Some(vec![])
is the user having no favorite foods!
None may mean unknown. Imagine you have a cache, or database with missing data. Empty list means no items for sure. Imagine a query is "past criminal record". In this case empty list would be important assumption to make, very different from "not checked yet".
Given a stock-ticker symbol, return a Vec of that company’s past monthly earnings.
None if that ticker-symbol isn’t a known company, vs an empty-Vec for a brand-new company.
Another fairly common example I haven't seen mentioned in this thread yet; when interacting with 3rd party data via JSON - there is often a difference between:
{
data: null
}
and:
{
data: []
}
When that's the case, you may need to be able to support both in your domain model.
(In most cases though, the reason for the 3rd party data model to support both is likely one of the reason mentioned in this thread - to differentiate between empty data, and the absence of data - e.g. the user wasn't asked the question vs they didn't check any of the possible answers; the company whose past earnings we are looking to return doesn't exist; etc.)
This kind of question reminds me of some JavaScript jokes... We can't let ourselves become like that.
In a nutshell, the semantics of None and Some([])—and even Some([""])—are different.