Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upordered ranges 2.0 #1254
Conversation
Gankro
referenced this pull request
Aug 14, 2015
Closed
Tracking issue for sorted collection ranges #27787
This comment has been minimized.
This comment has been minimized.
|
Would it be possible to remove the |
This comment has been minimized.
This comment has been minimized.
|
I'll admit L and R are sort-of artifacts of an earlier design -- the Note that today's Range allows L and R to have different types. In principle this enables searching with different borrows for different end-points. |
This comment has been minimized.
This comment has been minimized.
|
Yeah I agree that removing the type parameter does indeed reduce some functionality (e.g. not statically rule out erroneous situations), but making the signatures a little more readable and removing items from the public API are always nice! I also think it's a good point that the left/right bounds could be different types today, but I'm also not 100% convinced that this is necessary. |
This comment has been minimized.
This comment has been minimized.
|
Assuming pub struct Unbounded;instead of pub struct Unbounded<'a, Q: ?Sized + 'a>(PhantomData<&'a Q>); |
This comment has been minimized.
This comment has been minimized.
|
@apasel422 the associated types for the IntoBound trait don't work out, I think. |
This comment has been minimized.
This comment has been minimized.
|
@Gankro Yeah, |
This comment has been minimized.
This comment has been minimized.
|
I think a type parameters runs afoul of coherence/orphan checking in the IntoIter impl (which is why I didn't use Into). |
This comment has been minimized.
This comment has been minimized.
|
Hmm. I'm inclined to agree that we should just store the enums directly rather than use these marker types. We could still parameterize the range over multiple endpoint types though: use std::collections::Bound;
pub struct Range<'a, K: 'a, V: 'a, Min: ?Sized + 'a, Max: ?Sized + 'a> {
map: &'a Map<K, V>,
min: Bound<&'a Min>,
max: Bound<&'a Max>,
} |
This comment has been minimized.
This comment has been minimized.
|
Also, what are you planning to name these types if |
This comment has been minimized.
This comment has been minimized.
|
Uuugh naming.These can be called RangeBuilder or whatever I guess. |
This comment has been minimized.
This comment has been minimized.
|
Will the builder be hardcoded to store Could the builder itself also be parameterized over the collection? Then we could get away with one declaration like pub struct RangeBuilder<'a, C, Min: ?Sized + 'a, Max: ?Sized + 'a = Min> {
collection: C,
min: Bound<&'a Min>,
max: Bound<&'a Max>,
}
impl<'a, 'b, K, V, Min: ?Sized, Max: ?Sized> IntoIterator for RangeBuilder<'a, &'b BTreeMap<K, V>, Min, Max> where
K: Borrow<Min> + Borrow<Max> + Ord,
Min: Ord,
Max: Ord,
{
type IntoIter = btree_map::Range<'b, K, V>;
...
}
impl<'a, 'b, K, V, Min: ?Sized, Max: ?Sized> IntoIterator for RangeBuilder<'a, &'b mut BTreeMap<K, V>, Min, Max> where
K: Borrow<Min> + Borrow<Max> + Ord,
Min: Ord,
Max: Ord,
{
type IntoIter = btree_map::RangeMut<'b, K, V>;
...
}This would also enable more code reuse for external crates that want to provide the ordered query API. |
nrc
added
the
T-libs
label
Aug 17, 2015
This comment has been minimized.
This comment has been minimized.
bluss
commented
Aug 19, 2015
|
Let's question something we never do: Should the range really be double ended? I'm reasonably sure it has an irremovable overhead to support, and rust often claims to go for the least costly abstractions. Double ended iterators are nice where they are cheap, but here it has a cost (or is this wrong?). On the whole I think the range builder thing is fine, it's something users will recognize, even if it's not from other collections. |
This comment has been minimized.
This comment has been minimized.
|
@bluss That's another benefit of making range a builder: we can do that as different finalizers if it proves useful. By default I'd like to assume they'll be DoubleEnded, and investigate during/after implementation of the functionality that most would expect. |
This comment has been minimized.
This comment has been minimized.
|
@apasel422 What do you suggest that Drain's RangeBuilder contains? A newtype |
aturon
assigned
aturon and
Gankro
and unassigned
aturon
Aug 19, 2015
This comment has been minimized.
This comment has been minimized.
|
@Gankro Missed this earlier. I'm not sure I totally understand your question. |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Sep 10, 2015
|
@Gankro That sounds great |
This comment has been minimized.
This comment has been minimized.
|
@apasel422 If there is only one DrainBuilder, and |
alexcrichton
referenced this pull request
Sep 19, 2015
Closed
RangeArgument not exported to std::collections #28517
This comment has been minimized.
This comment has been minimized.
|
|
alexcrichton
added
the
final-comment-period
label
Oct 8, 2015
This comment has been minimized.
This comment has been minimized.
|
My personal preference would be to remove the two |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton what do you expect the behaviour of |
This comment has been minimized.
This comment has been minimized.
|
I'd want the upper bound of |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton I would expect the "other" sensible behavior. Listing a bunch of conditions looks very much like a conjunction to me, so |
This comment has been minimized.
This comment has been minimized.
|
I'm late to the party here, but I have some concerns about this RFC. First, I want to say that in isolation, I think a builder design like this is a pretty slick way of solving the problem. Kudos! However, I'm pretty concerned about the global design ramifications here. In particular, we've gradually been growing our range notation -- which is meant to be a generic way to express ranges, usable for a variety of purposes. We recently merged an RFC to add inclusive ranges. And we use this syntax heavily for indexed collections. It seems a real shame to have a completely different way of expressing ranges in the two cases, just because the syntax we happened to settle on doesn't support exclusivity on the left. I feel like this is a sign that we dropped the ball on the design of the range syntax, not accounting for the full, ahem, range of uses. In particular, if we had a design that allowed you to choose between exclusivity/inclusivity on both the left and the right -- basically, the equivalent to notation like Put differently, I fear it's going to be extremely annoying to get used to doing things like Given that inclusive ranges have not yet landed, I wonder whether we should take a step back and reconsider an overall range notation design that can express the full suite of ranges. |
This comment has been minimized.
This comment has been minimized.
|
Strawman proposal: the base syntax for ranges is
The modifier can be omitted on either or both sides, on the left it defaults to I actually like the currently accepted (This syntax seems so logical that I'm almost sure somebody has proposed it before: if so, my apologies!) |
This comment has been minimized.
This comment has been minimized.
|
@glaebhoerl Something along those lines seems pretty reasonable to me. I think in the previous round (Not sure whether we want to re-start the whole bikeshed within this RFC. But I'm going to raise my cross-cutting concerns here with the core team, since it feels like the incremental design work on the syntax side has not fully taken library concerns into account.) |
This comment has been minimized.
This comment has been minimized.
|
@aturon I feel somewhat similar. While reading the RFC, I thought "it's really unfortunate we can't reuse range notation for this." I will say though, that I do actually really like the API proposed. The bummer, as you say, is having two different ways to express ranges. Spending some extra time to see if there exists one way to express ranges might be worth it. |
This comment has been minimized.
This comment has been minimized.
|
The libs team discussed this RFC today and the decision was to move it out of FCP for now, but perhaps leave it open for a little more discussion. In light of @aturon's recent comment there's been some more thinking about this, and one idea brought up by @wycats was to perhaps have method syntax plus a builder to "emulate" what sugar one day might buy us. For example: fn range<T>() -> RangeBuilder<T> { /* ... */ }
impl<T> RangeBuilder<T> {
fn inclusive_left(&mut self, t: T) -> &mut Self { /* ... */ }
fn exclusive_left(&mut self, t: T) -> &mut Self { /* ... */ }
fn inclusive_right(&mut self, t: T) -> &mut Self { /* ... */ }
fn exclusive_right(&mut self, t: T) -> &mut Self { /* ... */ }
}
impl<T> RangeTrait<T> for RangeBuilder<T> {
/* ... */
}With this we'd have something like: impl<K, V> BTreeMap<K, V> {
fn range<T: RangeTrait<U>, U>(&self, t: T) -> Range<U> where K: Borrow<U> {
/* ... */
}
}The current range syntax we have (e.g. The general idea would be to introduce a more verbose library-based implementation of "all kinds of ranges" which can be supplanted with special sugar syntax later on if it becomes available. All along the way the Thoughts @Gankro? |
alexcrichton
removed
the
final-comment-period
label
Oct 15, 2015
This comment has been minimized.
This comment has been minimized.
|
Seem basically fine (the methods should be I'm a bit ambivalent about the temporary assymetry here. |
This comment has been minimized.
This comment has been minimized.
|
But wouldn't that mean we would end up, one day, with two kinds of syntax (not counting library methods here) to say whether the right-hand end of a range is inclusive? We'd have, e.g., |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Oct 16, 2015
|
@glaebhoerl I think that's a rather refreshing proposal, to not introduce inclusive range syntax. We could consider unshackling |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
|
@Gankro yeah the details of the actual API itself will likely be tweaked a bit, and I'd be fine with consumption so long as it turns out nicely. @RalfJung yeah I agree that it would lead us to a situation of "two ways to do the same thing", but I don't really see it as all that bad as it would in theory be a very well known and mechanical conversion. Additionally we'd perhaps deprecate the "builder API" if sugar was available instead. @bluss that's not a bad idea as well! I think the major question there is in terms of the ergonomics and what the downstream traits would look like for consuming a number of ranges, but otherwise it may obviate the need for |
This comment has been minimized.
This comment has been minimized.
|
Personally, I think any decent API for this problem shouldn't require importing anything. |
This comment has been minimized.
This comment has been minimized.
arthurprs
commented
Nov 19, 2015
|
Are there any note worthy implementations of this feature in other languages? |
This comment has been minimized.
This comment has been minimized.
|
This RFC is dead, pending the lang team investigating more complete range syntax. |
Gankro
closed this
Dec 9, 2015
bluss
referenced this pull request
Jan 15, 2016
Merged
Amend 1192 (RangeInclusive) to use an enum. #1320
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Mar 5, 2016
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Mar 6, 2016
This comment has been minimized.
This comment has been minimized.
robsmith11
commented
Jan 12, 2018
@Gankro Has this been resolved? |
Gankro commentedAug 14, 2015
Replace
range(Bound::Excluded(&min), Bound::Included(&max))withrange().ge(&min).lt(&max).Add BTreeMap::drain as appropriate.
Flesh out the general "ordered query" story.
Rendered