Rust: Tracking issue for `Option::contains` and `Result::contains`

Created on 4 Jul 2019  路  20Comments  路  Source: rust-lang/rust

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,
    }
}

``

A-result-option B-unstable C-tracking-issue Libs-Small Libs-Tracked T-libs

Most helpful comment

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.

All 20 comments

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?

Was this page helpful?
0 / 5 - 0 ratings