Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for RFC 2351, "Add is_sorted to the standard library" #53485

Open
6 of 10 tasks
Centril opened this issue Aug 19, 2018 · 45 comments
Open
6 of 10 tasks

Tracking issue for RFC 2351, "Add is_sorted to the standard library" #53485

Centril opened this issue Aug 19, 2018 · 45 comments
Labels
A-iterators Area: Iterators A-slice Area: [T] B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Centril
Copy link
Contributor

Centril commented Aug 19, 2018

Feature gate: #![feature(is_sorted)]

This is a tracking issue for is_sorted{_by,_by_key} functions on [T] and Iterator (rust-lang/rfcs#2351).

Public API

impl<T> [T] {
    pub fn is_sorted(&self) -> bool
    where
        T: PartialOrd;

    pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
    where
        F: FnMut(&'a T, &'a T) -> Option<Ordering>;

    pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
    where
        F: FnMut(&'a T) -> K,
        K: PartialOrd;
}
// core::iter

pub trait Iterator {
    // all the other methods omitted

    fn is_sorted(self) -> bool
    where
        Self: Sized,
        Self::Item: PartialOrd;

    fn is_sorted_by<F>(mut self, compare: F) -> bool
    where
        Self: Sized,
        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>;

    fn is_sorted_by_key<F, K>(self, f: F) -> bool
    where
        Self: Sized,
        F: FnMut(Self::Item) -> K,
        K: PartialOrd;
}

Steps / History

Unresolved Questions

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@Centril Centril added B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Aug 19, 2018
@LukasKalbertodt
Copy link
Member

LukasKalbertodt commented Aug 19, 2018

@gnzlbg Would you be interested in implementing this? You basically already wrote the code. I think it would be fancy to have this SIMD code in the standard library. (Or should we start with only the fully generic algorithm?). PS: Sorry for not having reviewed #53386 yet -- I hope I'll find the time and mental capacity to do that in the near future!

@Centril The links for the unresolved questions are dead (still pointing to the 0000 file). Could you or anyone update them? :)


Regarding the "Should Iterator::is_sorted_by_key be added as well?" question: this last minute comment in the RFC thread argues that this method should be added:

I feel like it is not a question about how easy it is to do it yourself using map but more about completeness of the api.

And people seem to agree. So I'd also say that this method should be added.

@Centril
Copy link
Contributor Author

Centril commented Aug 19, 2018

@LukasKalbertodt done :)

@Centril
Copy link
Contributor Author

Centril commented Aug 19, 2018

cc @SimonSapin re. the unresolved questions (particularly around is_sorted_by_key).

@gnzlbg
Copy link
Contributor

gnzlbg commented Aug 20, 2018

I don't know when I can work on this, but I can mentor anyone wanting to implement this or wanting to port the implementation of the is_sorted crate.

@SimonSapin
Copy link
Contributor

Oh, I didn’t realized that Iterator::is_sorted_by_key was not part of the RFC when I proposed FCP. I thought there was consensus to include it for consistence, both internal and with the existing sort_by_key/min_by_key/max_by_key methods which are also redundant with their respective method like sort_by.

We do have precedent of adding some APIs that can be expressed as a terse combination of existing APIs: #49098

@clarcharr, you expressed the opposite in rust-lang/rfcs#2351 (comment). Do you still think it should not be included?

@clarfonthey
Copy link
Contributor

At the time I made that comment, I didn't realise that max_by_key and min_by_key were already stable (as of 1.6, which is a while ago). Basically, there are two options:

  1. Deprecate max_by_key and min_by_key and don't add is_sorted_by_key.
  2. Add is_sorted_by_key.

I feel like the usefulness of these should be re-evaluated, as it forces the key to outlive any reference to self rather than just the current reference to self. Basically, we'd need something similar to GAT for it to be useful, and map already exists.

Personally, I'd prefer option 1. But option 2 is also acceptable and there may be a way to make these functions work with GAT in the future.

@gnzlbg
Copy link
Contributor

gnzlbg commented Aug 23, 2018

@SimonSapin would you like to be the reviewer of a PR implementing this ? If so, I'd like to discuss with somebody first how the is_sorted crate is structure, and how to best implement this functionality in the std library.

@gnzlbg
Copy link
Contributor

gnzlbg commented Aug 30, 2018

So I don't know how to properly implement this in core.

The is_sorted functionality should use intrinsics when available at run-time. The iter and slice modules in core do not have access to run-time detection (that requires std), but e.g. the Iterator trait exported by core and std has to be the same, so we can't override the core implementation in std to add run-time detection on top.

After talking with @SimonSapin on IRC, I am just going to add the naive versions to core which get picked up by std and call it a day. Those who need more performance can just use is_sorted from crates.io. Adding vectorized versions of the is_sorted functionality isn't worth it either, because one would need to re-compile core to profit from it (using crates.io is just easier). Maybe if we get newer targets in the future with more features enabled this might become worth it.

@kleimkuhler
Copy link
Contributor

I have interest in working on this RFC. This would be a significant learning experience for me, but I don't see any reason why I should not be able to complete it.

@gnzlbg If your offer for being available as a mentor is still open, I'd like to take you up on that!

If there is any concern in timeline (I should be able to begin implementing this week) or preference for someone who may have more experience, I have no problem with that; just let me know!

@gnzlbg
Copy link
Contributor

gnzlbg commented Oct 8, 2018

An efficient implementation of this is probably blocked on rust-lang/rfcs#2492 (e.g. see rust-lang/rfcs#2492 (comment)) , since until then we cannot really use SIMD in libcore effectively.

My recommendation is that if you want to implement this now, you should just adapt rust-itertools/itertools#261 which is a straight-forward plain Rust implementation. Maybe with some tweaks one can get it to auto-vectorize in some cases. This would allow us to get experience with the API until the other problems are solved.

@kleimkuhler
Copy link
Contributor

Thanks for the links; it makes sense that a more efficient implementation is blocked on that right now.

To clarify on my initial comment (and what you picked up on in your last sentence), is the "learning" part of this would be more related to familiarizing myself with the API and codebase.

I think an initial implementation based off rust-itertools/itertools#261 could be a good first step and we'll keep an eye on the progress of rust-lang/rfcs#2492?

@kleimkuhler
Copy link
Contributor

@gnzlbg You'll find my initial implementation in the PR above (#55045). I'm not sure who should be officially reviewing this, but I can update the PR if need be!

@kleimkuhler
Copy link
Contributor

@SimonSapin It was asked a few comments up if you'd like to be the reviewer of this PR? I still need to assign someone to review it, but I'm just not sure who.

bors added a commit that referenced this issue Jan 21, 2019
Add `is_sorted` to `Iterator` and `[T]`

This is an initial implementation for the first step of [RFC 2351](https://github.com/rust-lang/rfcs/blob/master/text/2351-is-sorted.md)

Tracking issue: #53485
@mtak-
Copy link
Contributor

mtak- commented Jan 23, 2019

This has broken the is_sorted crate on nightly. Is the only workaround to turn the feature flag on or use an older nightly?

   --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/is_sorted-0.1.0/src/lib.rs:119:31
    |
119 |         self.map(|v| key(&v)).is_sorted()
    |                               ^^^^^^^^^
    |
    = help: add #![feature(is_sorted)] to the crate attributes to enable

@clarfonthey
Copy link
Contributor

Call IsSorted::is_sorted directly.

@mtak-
Copy link
Contributor

mtak- commented Jan 23, 2019

@clarcharr The above error happens when adding is_sorted as a dependency (without using it). The is_sorted crate itself no longer builds.

@CryZe
Copy link
Contributor

CryZe commented Jan 23, 2019

You can send a PR to the is_sorted crate and use the patch section in your Cargo.toml in the meantime until it is merged and published.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jan 23, 2019

@mtak- thank you for the PR, i've merged it already, will fix the doc tests and do a release so that the world keeps going.

The collision between the is_sorted crate and this PR was expected, I guess I could have fixed that a priori. Sorry about that. Keep in mind that if you are using the is_sorted crate, if you don't disambiguate your code the implementations of libcore will be picked after a re-compile.

Manishearth added a commit to Manishearth/rust that referenced this issue Nov 16, 2022
remove HRTB from `[T]::is_sorted_by{,_key}`

Changes the signature of `[T]::is_sorted_by{,_key}` to match `[T]::binary_search_by{,_key}` and make code like rust-lang#53485 (comment) compile.

Tracking issue: rust-lang#53485

~~Do we need an ACP for something like this?~~ Edit: Filed ACP here: rust-lang/libs-team#121
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 18, 2022
remove HRTB from `[T]::is_sorted_by{,_key}`

Changes the signature of `[T]::is_sorted_by{,_key}` to match `[T]::binary_search_by{,_key}` and make code like rust-lang#53485 (comment) compile.

Tracking issue: rust-lang#53485

~~Do we need an ACP for something like this?~~ Edit: Filed ACP here: rust-lang/libs-team#121
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 18, 2022
remove HRTB from `[T]::is_sorted_by{,_key}`

Changes the signature of `[T]::is_sorted_by{,_key}` to match `[T]::binary_search_by{,_key}` and make code like rust-lang#53485 (comment) compile.

Tracking issue: rust-lang#53485

~~Do we need an ACP for something like this?~~ Edit: Filed ACP here: rust-lang/libs-team#121
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 18, 2022
remove HRTB from `[T]::is_sorted_by{,_key}`

Changes the signature of `[T]::is_sorted_by{,_key}` to match `[T]::binary_search_by{,_key}` and make code like rust-lang#53485 (comment) compile.

Tracking issue: rust-lang#53485

~~Do we need an ACP for something like this?~~ Edit: Filed ACP here: rust-lang/libs-team#121
@leonardo-m
Copy link

If slice::sort uses F: FnMut(&T, &T) -> Ordering, then perhaps is_sorted_by could use the same.

thomcc pushed a commit to tcdi/postgrestd that referenced this issue Feb 10, 2023
remove HRTB from `[T]::is_sorted_by{,_key}`

Changes the signature of `[T]::is_sorted_by{,_key}` to match `[T]::binary_search_by{,_key}` and make code like rust-lang/rust#53485 (comment) compile.

Tracking issue: rust-lang/rust#53485

~~Do we need an ACP for something like this?~~ Edit: Filed ACP here: rust-lang/libs-team#121
@nm17
Copy link

nm17 commented Feb 19, 2023

A suggestion: Rust compiler should raise a compiler error when is_sorted or one of the related functions is called on keys or values of a HashMap, since depending on their order is UB.

@clarfonthey
Copy link
Contributor

Depending on the order of items in a HashMap isn't UB; the order is just not guaranteed. The difference here is one thing is unsafe and one is just a bad idea.

bluebear94 added a commit to bluebear94/rust that referenced this issue Jun 16, 2023
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 21, 2023
…r=cuviper

Add more comprehensive tests for is_sorted and friends

See rust-lang#53485 and rust-lang#55045.
chenyukang pushed a commit to chenyukang/rust that referenced this issue Jul 22, 2023
@rdrpenguin04
Copy link

"Revisit test suite" can probably be checked off due to #112699.

I feel like this could probably be stabilized as-is, and more could be added in later.

@WaffleLapkin WaffleLapkin added the A-iterators Area: Iterators label Sep 19, 2023
@WaffleLapkin
Copy link
Member

Nominating for T-libs-api: this API existed for a while, and the only question left seems to be whatever cmp::is_sorted would be a better API option. Thus, I'm proposing stabilization :)

Note: while trying to check the implementation history I've updated the issue text with the newer format, hopefully it makes it easier to understand what this issue tracks, exactly.

While doing that I've also found two questions in the comments that did not seem to be fully answered:

@WaffleLapkin WaffleLapkin added the I-libs-api-nominated The issue / PR has been nominated for discussion during a libs-api team meeting. label Sep 19, 2023
@m-ou-se
Copy link
Member

m-ou-se commented Oct 17, 2023

We dicsussed this in a recent libs-api meeting.

  • Using bool rather than Option<Ordering> for the return value of the closure to is_sorted_by seems clearer and more flexible. E.g. then you can use a < b or a <= b depending on whether it should be strictly increasing or not, etc.
  • There wasn't much enthusiasm for adding a function to return the position up to which everything is sorted. That is easy enough to write manually, and is probably too niche to warrant its own function. Iterator has convenience methods for common operations, but it doesn't need a method for every possible operation.

@m-ou-se m-ou-se removed the I-libs-api-nominated The issue / PR has been nominated for discussion during a libs-api team meeting. label Oct 17, 2023
@Jules-Bertholet
Copy link
Contributor

This was already mentioned earlier, but is_sorted_by_key, like all the by_key methods, suffers from #34162; a fix would require removing the K type parameter.

Nadrieril added a commit to Nadrieril/rust that referenced this issue Jan 21, 2024
…Simulacrum

Use `bool` instead of `PartiolOrd` as return value of the comparison closure in `{slice,Iteraotr}::is_sorted_by`

Changes the function signature of the closure given to `{slice,Iteraotr}::is_sorted_by` to return a `bool` instead of a `PartiolOrd` as suggested by the libs-api team here: rust-lang#53485 (comment).

This means these functions now return true if the closure returns true for all the pairs of values.
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jan 21, 2024
Rollup merge of rust-lang#118811 - EbbDrop:is-sorted-by-bool, r=Mark-Simulacrum

Use `bool` instead of `PartiolOrd` as return value of the comparison closure in `{slice,Iteraotr}::is_sorted_by`

Changes the function signature of the closure given to `{slice,Iteraotr}::is_sorted_by` to return a `bool` instead of a `PartiolOrd` as suggested by the libs-api team here: rust-lang#53485 (comment).

This means these functions now return true if the closure returns true for all the pairs of values.
lnicola pushed a commit to lnicola/rust-analyzer that referenced this issue Apr 7, 2024
Use `bool` instead of `PartiolOrd` as return value of the comparison closure in `{slice,Iteraotr}::is_sorted_by`

Changes the function signature of the closure given to `{slice,Iteraotr}::is_sorted_by` to return a `bool` instead of a `PartiolOrd` as suggested by the libs-api team here: rust-lang/rust#53485 (comment).

This means these functions now return true if the closure returns true for all the pairs of values.
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 27, 2024
Use `bool` instead of `PartiolOrd` as return value of the comparison closure in `{slice,Iteraotr}::is_sorted_by`

Changes the function signature of the closure given to `{slice,Iteraotr}::is_sorted_by` to return a `bool` instead of a `PartiolOrd` as suggested by the libs-api team here: rust-lang/rust#53485 (comment).

This means these functions now return true if the closure returns true for all the pairs of values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-iterators Area: Iterators A-slice Area: [T] B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests