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 sorted collection ranges #27787

Closed
Gankra opened this issue Aug 13, 2015 · 92 comments
Closed

Tracking issue for sorted collection ranges #27787

Gankra opened this issue Aug 13, 2015 · 92 comments
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. E-help-wanted Call for participation: Help is requested to fix this issue. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Gankra
Copy link
Contributor

Gankra commented Aug 13, 2015

This covers btree_range and collections_bound. Both try to address the combinatorics over inclusive/exclusive/none bounds on ordered queries. I am significantly unsatisfied with the current solution, which is btree.range(Bound(&K), Bound(&K)). This pushes all the combinatorics into a nasty calling convention. Instead, I believe we would be better served by a build pattern:

for x in btree.range().ge(&min).lt(&max) { .. }

This allows you to avoid importing and dispatching on enum. It also has the advantage of making simpler queries simpler. Compare:

// today (assuming you've totally imported the bound variants)
for x in btree.range(Unbounded, Inclusive(&max)) {

// tomorrow?
for x in btree.range().le(&max) { .. }

This also could potentially address rust-lang/rfcs#1195

let pred = btree.range().le(&max).get();

And can be extended to support drain or remove similarly;

for x in btree.range_mut().gt(&min).drain() { .. }
ler pred = btree.range_mut().le(&max).remove();

Which if desirable can be sugarred to direct methods on btree in the future.

@Gankra Gankra added the B-unstable Blocker: Implemented in the nightly compiler and unstable. label Aug 13, 2015
@Gankra Gankra changed the title sorted collection ranges Tracking issue for sorted collection ranges Aug 13, 2015
@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

CC @bluss @apasel422

@apasel422
Copy link
Contributor

Will this still allow for efficient implementations of things like just the
predecessor (without iteration)?

On Wednesday, August 12, 2015, Alexis Beingessner notifications@github.com
wrote:

CC @bluss https://github.com/bluss @apasel422
https://github.com/apasel422


Reply to this email directly or view it on GitHub
#27787 (comment).

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

@apasel422 Yes the builder is completely lazy -- get would just extract the one set bound and do lt/le/gt/whatever as appropriate.

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

I should note the builder API is considerably more hairy internally. Basically requires converting all the static types into dynamic types and then dispatching to the existing impls (for IntoIter) or those proposed in rust-lang/rfcs#1195

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

Shoutouts to @zentner-kyle for proposing this API. Big improvement.

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

In practice, with the parent pointer design I anticipate the guts of BTreeMap having the query API just do raw pointers and be an internal impl detail: get_lt(&BTreeMap, &Q) -> Handle<*mut Node>

A range knows how to compute handles from bounds by dispatching to the query API, and then get or into_iter are just munging up handles into a (K, V) pair or Iter(Handle, Handle).

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

@apasel422 does this sound good to you?

@Gankra
Copy link
Contributor Author

Gankra commented Aug 13, 2015

CC @cgaebel @glaebhoerl @jooert

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Aug 13, 2015
@Gankra
Copy link
Contributor Author

Gankra commented Aug 14, 2015

I have made an RFC to this affect: rust-lang/rfcs#1254

@alexcrichton
Copy link
Member

Removing the B-unstable tag as I believe these haven't been implemented.

@alexcrichton alexcrichton added A-libs and removed B-unstable Blocker: Implemented in the nightly compiler and unstable. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 27, 2016
@Gankra Gankra added the B-unstable Blocker: Implemented in the nightly compiler and unstable. label Jan 28, 2016
@Gankra
Copy link
Contributor Author

Gankra commented Jan 28, 2016

@alexcrichton range and range_mut have been around since 1.0, I think. But they won't be stabilized as-is.

@alexcrichton
Copy link
Member

Oh oops there are indeed some unstable APIs tagged with this.

@alexcrichton alexcrichton added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed A-libs labels Jan 28, 2016
@naktinis
Copy link

What's the state of this? I'm using btree ranges in production code and would be happy to help as much as I can to stabilize this feature.

@calebmer
Copy link

I also would like to know the status as I'm building a program which uses ranges and if there is an idiomatic rust solution I'd love to use that over my own implementation.

@apasel422
Copy link
Contributor

My understanding is that we're waiting on a new RFC in lieu of rust-lang/rfcs#1254.

@naktinis
Copy link

How can we contribute to the discussion or at least keep track of the remaining issues?

@apasel422
Copy link
Contributor

@naktinis A pre-RFC or general discussion thread on https://internals.rust-lang.org/ would probably work.

@alexcrichton
Copy link
Member

cc #33197, a case where the APIs currently segfault apparently

@ticki
Copy link
Contributor

ticki commented May 9, 2016

It seems to me that the extension Bound provides over Range is very small. I wonder why .range() doesn't take Range instead.

@apasel422
Copy link
Contributor

@ticki Range is [start, end), but Bound provides inclusive/exclusive/unbounded on both ends.

bors added a commit that referenced this issue Jan 15, 2017
Implementation of plan in issue #27787 for btree_range

Still some ergonomics to be worked on, the ::<str,_> is particularly unsightly
@aturon
Copy link
Member

aturon commented Feb 3, 2017

Now that the changes to the surface API have landed, I think we're ready to consider stabilization.

@rfcbot rfc merge

@aturon
Copy link
Member

aturon commented Feb 3, 2017

Grr:

@rfcbot fcp merge

@rfcbot
Copy link

rfcbot commented Feb 3, 2017

Team member @aturon has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@alexcrichton
Copy link
Member

@aturon, to clarify, what APIs are you thinking of stabilizing as part of this? Just BTreeMap::range{,_mut} or also the RangeArgument trait and associated types?

@aturon
Copy link
Member

aturon commented Feb 3, 2017

@alexcrichton I think we should start with just the method for now, and let the trait bake a while longer.

@alexcrichton
Copy link
Member

In that case you have my checkmark!

@djzin
Copy link
Contributor

djzin commented Feb 4, 2017

There is a small ergonomic issue I came across while writing tests for this relating to taking a range by borrowed key; say you have a map with strings as keys, then it would be nice to just use range syntax to specify the range. Unfortunately this doesn't work, because you would need a Range<str> which is unsized. Changing the bounds required type annotations in the common case. Instead what I did is implement RangeArgument<T> for (Bound<&T>, Bound<&T>), allowing you to do this, but it still requires type annotations.

#![feature(btree_range)]
#![feature(collections_bound)]

use std::collections::btree_map::BTreeMap;
use std::collections::Bound::*;

fn main() {
    let mut map = BTreeMap::new();
    map.insert("key".to_string(), "value".to_string());
    map.insert("lee".to_string(), "walue".to_string());
    map.insert("me".to_string(), "xalue".to_string());
    // let range = map.range("key".."me"); // doesn't work
    // let range = map.range((Included("key"), Excluded("me"))); // type annotations required
    let range = map.range::<str, _>((Included("key"), Excluded("me"))); // finally
    for (key, value) in range {
        println!("({}, {})", key, value);
    }
}

I suppose this is covered by not stabilizing RangeArgument, though?

@aturon
Copy link
Member

aturon commented Feb 6, 2017

@djzin We have to be a bit careful: once the range method is stabilized, we're committing to it working for at least all of the arguments allowed by today's definition of RangeArgument. That is, we can change the definition and impls for RangeArgument but only if all uses of range will continue to work.

@bluss
Copy link
Member

bluss commented Feb 7, 2017

I propose that #33197 should be fixed before stabilization (unfortunately), but it's being fixed.

@rfcbot
Copy link

rfcbot commented Feb 13, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot added the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Feb 13, 2017
@rfcbot
Copy link

rfcbot commented Feb 13, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

1 similar comment
@rfcbot
Copy link

rfcbot commented Feb 13, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

@djzin
Copy link
Contributor

djzin commented Feb 18, 2017

The first issue I listed above (not being able to use range syntax) may be fixed at a later time by adding impls such as

impl<'a, T: ?Sized> RangeArgument<T> for Range<&'a T> {
    fn start(&self) -> Bound<&T> { Included(self.start) }
    fn end(&self) -> Bound<&T> { Excluded(self.end) }
}

Then one may use map.range::<str, _>("a".."z").
A similar impl could be provided for &'a mut T if that were a thing.

For some reason, even though there is only one type that can fit here (as far as I can tell), rust still requires type annotations for the str. This seems to me like improvements in rust's type inference down the line may fix this ergonomic issue.

A related problem occurs with RangeFull aka .. - rust cannot derive the type for a String key. In this case there are multiple options, all with the same result. I feel as though this is a non-issue as selecting the whole range is a no-op.

None of these issues affect BTreeMaps with an i64 key (or any key that has no nontrivial implementation of Borrow), and the main ones are solvable in future backwards-compatibly. So I think, as this feature has been in unstable limbo for so long, it's due its chance to shine in stable rust-land :)

@rfcbot
Copy link

rfcbot commented Feb 23, 2017

The final comment period is now complete.

frewsxcv pushed a commit to frewsxcv/rust that referenced this issue Mar 17, 2017
alexcrichton pushed a commit to alexcrichton/rust that referenced this issue Mar 17, 2017
@bors bors closed this as completed in 37b38a2 Mar 19, 2017
@Gankra
Copy link
Contributor Author

Gankra commented Mar 29, 2017

!?!? REALLY?

@solson
Copy link
Member

solson commented Mar 29, 2017

@gankro I was shocked too: rust-lang/miri#155 :)

this feature has been stable since ____. Attribute no longer needed is the best warning in rustc.

@cgaebel
Copy link
Contributor

cgaebel commented Mar 29, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. E-help-wanted Call for participation: Help is requested to fix this issue. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. 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