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

Syntax for RangeFull: .. #702

Merged
merged 3 commits into from
Feb 3, 2015
Merged

Syntax for RangeFull: .. #702

merged 3 commits into from
Feb 3, 2015

Conversation

bluss
Copy link
Member

@bluss bluss commented Jan 21, 2015

Add the syntax .. for std::ops::RangeFull.

Range expressions a..b, a.. and ..b all have dedicated syntax and produce first-class values. This means that they will be usable and useful in custom APIs, so for consistency, the fourth slicing range, RangeFull, could have its own syntax ..

Rendered Version

@bluss
Copy link
Member Author

bluss commented Jan 21, 2015

Previously discussed here as well as discussions in #rust-internals. It has come up again due to deref coercions enabling &foo for many common "as_slice" use cases already, and because of ideas around using ranges in collection APIs.

I have already implemented this (draft impl) (on top of the PR rust-lang/rust#21374) it is a very simple change to make. dgrunwald's PR (Note: that has been merged) is also relevant because it fixes some grammar issues around the range syntax.

cc @gankro.

@Gankra
Copy link
Contributor

Gankra commented Jan 21, 2015

I'd also like to add that .. is the only valid range to apply to a HashMap, if that's a thing we're interested in doing.

👍 from me, makes the language more consistent and opens up cool patterns.

@quantheory
Copy link
Contributor

Note that there may be a few new edge cases. For instance, is &..-y equivalent to (&FullRange) - y or &(..(-y)) (or a syntax error)?

@blaenk
Copy link
Contributor

blaenk commented Jan 22, 2015

Yes PLEASE. Thanks @bluss for writing this!

I really really really hope the team considers this. It's just much more consistent to have .. considering we already have a.., ..b, and a..b.

Previously the team seemingly decided against it stating that [] was shorter, but for the most prevalent (?) use cases we will now have simply &string and &vec thanks to deref coercions. I really hope the team is reasonable here. For types that want to encode range semantics, [] just looks completely irregular alongside the others.

@ghost
Copy link

ghost commented Jan 22, 2015

👍 I'm in favor of this. It makes sense since for most use cases we will have an even shorter way of cross borrowing, like &string and &vector.

@ftxqxd
Copy link
Contributor

ftxqxd commented Jan 22, 2015

👍 I agree with the RFC’s motivation for this: people are now beginning to recognise the use of ranges outside slicing alone: things like vec.remove(..) have been proposed recently. Because of that, having .. is not only more consistent, but more useful as well. Now that we have deref coercions, writing &foo[]/&foo[..] will probably be very rare, so the conciseness of full-range slicing doesn’t really matter. Full ranges are still potentially useful outside slicing alone, so to me, the most advantageous option is to use ...

@quantheory That particular case would be &(..(-y)) due to the precedence of .., but there might be some other less obvious cases.

@bluss
Copy link
Member Author

bluss commented Jan 22, 2015

It wasn't stressed enough in the RFC that we will probably want to use ranges a in future libstd API, it's not just about third party crates.

@bluss
Copy link
Member Author

bluss commented Jan 22, 2015

@dgrunwald
Copy link
Contributor

@quantheory I don't think there are any new grammar edge cases, all the strangeness with this syntax can also be done with the existing a.. and ..a syntax.

@P1start: &..-y will actually be a syntax error with my PR: .. has a lower operator precedence than &; thus .. cannot be used as an operand to & without using parentheses, even if the expression could be parsed unambiguously when ignoring operator precedence. (this rule will prevent a lot of strange 'precedence reversal' cases that currently occur when combining .. with some other operators)

Without the &:
..-y will continue to be parsed as ..(-y) because .. has lower precedence than -. Note that this isn't new (x..-y is the same situation), and is not actually an ambiguity (parsing it as (x..)-y would go against the operator precedence).

@kennytm
Copy link
Member

kennytm commented Jan 24, 2015

Note that existing code using .. in pattern matching will be broken when this RFC is merged:

enum Foo {
    A(i32, i32),
    B(u32, u32, u64),
}
fn main() {
    let k = Foo::A(1, 2);
    let q = match k {
        Foo::A(..) => 1,
        Foo::B(..) => 2,
    };
    assert_eq!(q, 1);
}

Examples:

This RFC should propose an alternate syntax of the above, after .. is changed to mean FullRange.

@bluss
Copy link
Member Author

bluss commented Jan 24, 2015

Very good catch. It doesn't break anything (range syntax is not parsed in patterns, only in expressions), but it's a confusing conflict. We'll have to discuss this issue.

@huonw
Copy link
Member

huonw commented Jan 25, 2015

On patterns, we also have [a, b..] for slice patterns.

It wasn't stressed enough in the RFC that we will probably want to use ranges a in future libstd API, it's not just about third party crates.

e.g. #722 wants it.

@nikomatsakis
Copy link
Contributor

Regarding patterns, I think that overlap already exists, it doesn't seem especially bothersome to me.

@tikue
Copy link
Contributor

tikue commented Jan 28, 2015

Strong +1 here. The consistency argument is compelling enough to me, but the fact that Ranges have identified use cases outside of indexing seals the deal.

@rkjnsn
Copy link
Contributor

rkjnsn commented Jan 28, 2015

👍, for all of the reasons mentioned above.

@bluss
Copy link
Member Author

bluss commented Jan 30, 2015

  • Updated for the new name of the struct.
  • Updated text to mention the drawback of overlap with .. in patterns.

@bluss bluss changed the title Syntax for FullRange: .. Syntax for RangeFull: .. Jan 30, 2015
@quantheory
Copy link
Contributor

I may as well point out that RFC 520 already states that .. in patterns is never interpreted as being a part of range syntax, since as @huonw mentioned there would have been an ambiguity with slice patterns otherwise. So this doesn't introduce much more of an inconsistency with patterns than we already had.

@bluss
Copy link
Member Author

bluss commented Jan 30, 2015

Slice patterns are more niche than using .. in patterns like this: match foo { Some(..) => though.

@quantheory
Copy link
Contributor

Maybe. Personally, I've used slice patterns moderately often, because I work with various array-like types a lot. I use wildcards pretty rarely, in part because I typically use a pattern like Some(_) for variants that only hold one item.

@nrc nrc assigned nrc and unassigned aturon Feb 1, 2015
@nrc nrc merged commit 25d35f1 into rust-lang:master Feb 3, 2015
@nrc
Copy link
Member

nrc commented Feb 3, 2015

Merged, r = @nikomatsakis, @huonw

Tracking issue: rust-lang/rust#21879

RFC: https://github.com/rust-lang/rfcs/blob/master/text/0702-rangefull-expression.md

This RFC has been accepted since it is a popular and minor improvement to the range syntax which has multiple use cases. Since we don't accept range syntax in patterns, we don't think there is any reason to worry about a clash of syntax there.

bors added a commit to rust-lang/rust that referenced this pull request Feb 6, 2015
Implement step 1 of rust-lang/rfcs#702

Allows the expression `..` (without either endpoint) in general, can be
used in slicing syntax `&expr[..]` where we previously wrote `&expr[]`.

The old syntax &expr[] is not yet removed or warned for.
@caipre
Copy link

caipre commented Feb 15, 2015

Regarding range syntax in patterns: we actually do accept ranges, but with ... rather than ... In patterns, the former allows a branch arm to match any value within a range while the latter can be used to ignore values when they won't be used in the match expression. Examples of each can be found in the Patterns chapter of the book.

I think it would be worth discussing whether we can swap the syntax here: .. should mean "range" inside patterns for consistency with the rest of the language, and ... reads well as an ellipsis, ie, "extra values ignored". Using ... as a placeholder for code also has precedent in Perl as the "yada yada" operator (though it's more akin to Python's pass than to Rust's current usage of .. in patterns).

Though the underlying objects / types may be different between ... ranges inside patterns and .. ranges outside of them, it seems to me that the semantics / intent is the same in both contexts.

Edit: It looks like the different meanings of .. are mentioned in RFCs 520 and 702. I don't see any further discussion though, and neither one discusses the ... syntax.

@bluss
Copy link
Member Author

bluss commented Feb 15, 2015

The discussion of inclusive range syntax is taking place, it's here!

@caipre
Copy link

caipre commented Feb 15, 2015

@bluss : Thanks for the link. It seems like Niko explicitly requested not to discuss use of range syntax in patterns in that thread though:

I would prefer not to have this thread derailed with a generic discussion of whether .. or ... is preferable in other cases (e.g. patterns), nor the question of whether .. in patterns ought to destructure a range vs matching a range.

@Centril Centril added A-syntax Syntax related proposals & ideas A-expressions Term language related proposals & ideas A-ranges Proposals relating to ranges. labels Nov 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-expressions Term language related proposals & ideas A-ranges Proposals relating to ranges. A-syntax Syntax related proposals & ideas
Projects
None yet
Development

Successfully merging this pull request may close these issues.