This is a tracking issue for Option::contains
and Result::contains
.
The implementations are as follows:
```rust
pub fn contains(&self, x: &T) -> bool where T: PartialEq {
match self {
Some(y) => y == x,
None => false,
}
}
pub fn contains(&self, x: &T) -> bool where T: PartialEq {
match self {
Ok(y) => y == x,
Err(_) => false,
}
}
``
Should we update the signatures to fn contains<U>(&self, x: &U) -> bool where T: PartialEq<U>
?
@Mark-Simulacrum That seems like a good idea -- type inference should be driven by x
in any case. Let's do that in the PR.
Looks like slice
/Vec
/VecDeque
/LinkedList
and possibly others have a contains
method that could benefit in the same way.
@Mark-Simulacrum I didn't do that because I checked the collections first, and they were all invariant. Shall I change this for Option
and Result
only?
We usually can't change preexisting APIs due to inference breakage, but since this is new, we should be able to be general.
Are these functionally equivalent?
pub fn contains(&self, x: &T) -> bool where T: PartialEq {
match self {
Some(y) => y == x,
None => false,
}
}
pub fn contains(&self, x: &T) -> bool where T: PartialEq {
self.as_ref() == Some(x)
}
@frewsxcv Not quite, due to the requested variance changes.
What does that mean @soc?
@czipperz The implementation is:
// Option
pub fn contains<U>(&self, x: &U) -> bool where U: PartialEq<T> {
match self {
Some(y) => x == y,
None => false,
}
}
// Result
pub fn contains<U>(&self, x: &U) -> bool where U: PartialEq<T> {
match self {
Ok(y) => x == y,
Err(_) => false
}
}
pub fn contains_err<F>(&self, f: &F) -> bool where F: PartialEq<E> {
match self {
Ok(_) => false,
Err(e) => f == e
}
}
The argument doesn't have to be of the same type as the value inside option/result, only that it knows how to compare itself to it. I. e. the operation is not invariant on the contained type, it allows an arbitrary type.
So there's no implementation of PartialEq<Option<U>> for Option<T> where U: PartialEq<T>
?
There is indeed not, see #20063.
These methods are way too high up in the docs on both the Option
and Result
rustdoc. Would someone be able to send a PR to move these a lot further down? For example stuff like ok
and map
and and_then
should all be featured higher than contains.
What is the status on this? I would love to use these in stable.
Assume you have a function getFoo()
returning Option<String>
then it might be misleading if you do getFoo().contains("bar")
since it looks like it checks for a substring when it in fact checks for an exact match. Would some other name perhaps be more clear?
how about contains_in
or map_contains
?
option.contains_in("foo")
reads weird. You could of course pick something else entirely different, like option.has("foo")
or option.includes("foo")
.
But in the end, Rust is a typed language, so we should not be scared that much about confusion, because the types tell us which contains
method is used.
Naming bikeshed. Sorry if this is the wrong place.
How about the names eq_some
, eq_ok
and eq_err
? Or maybe only using those names for Result
? I get that contains
is consistent with containers, but that analogy weakens especially with Result
.
I'm quite surprised bikeshedders have not suggested wraps
yet, so I guess I'll be that person. ;)
This would be consistent with both Option
and Result
, and also unwrap
.
I think wraps
has nice symmetry (though I wonder what's a good approach for Result
: wraps_err
/err_wraps
?).
I haven't chosen it, because I think unwrap
is a terrible name and probably will be deprecated in the long-term, so I don't want to add methods with names that could be an obstacle to that.
if unwrap
is going to be renamed in the long-term, why not rename a theoretical Option#wraps
at the same time?
Most helpful comment
option.contains_in("foo")
reads weird. You could of course pick something else entirely different, likeoption.has("foo")
oroption.includes("foo")
.But in the end, Rust is a typed language, so we should not be scared that much about confusion, because the types tell us which
contains
method is used.