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

"Use" in patterns (to match an expression’s value) #2272

Closed
SoniEx2 opened this issue Dec 29, 2017 · 15 comments
Closed

"Use" in patterns (to match an expression’s value) #2272

SoniEx2 opened this issue Dec 29, 2017 · 15 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@SoniEx2
Copy link

SoniEx2 commented Dec 29, 2017

"Use" in patterns would introduce a new feature and fix a small pain point in current Rust.

Currently this doesn't work:

fn main() {
    let x = 1;
    let y = 2;
    match x {
        y => println!("{} {}", x, y),
        z => println!("{} {} {}", x, y, z)
    }
}

I propose "use" in patterns so that it can be made to work:

fn main() {
    let x = 1;
    let y = 2;
    match x {
        use y => println!("{} {}", x, y),
        z => println!("{} {} {}", x, y, z)
    }
}

"use" in patterns should take an expression, no reason to accept only variables if you can just put the result of any expression in a variable.

This can also be combined with destructuring:

fn main() {
    let x = Some(1);
    let y = 2;
    match x {
        Some(use y) => println!("{} {}", x, y),
        Some(z) => println!("{} {} {}", x, y, z),
        None => {}
    }
}

Another effect of "use" in patterns can be summarized in "WHY'S RUST CONTEXT-SENSITIVE?!". Check out the following code (assume the author is using #[allow(non_snake_case)]):

const SOMETHING: u32 = 2; // (un)comment to break
let x = 1;
let v = 0;
match x {
  SOMETHING if v < 10 => println!("<10 {} {}", x, SOMETHING),
  SOMETHING if v < 5 => println!("<5 {} {}", x, SOMETHING),
  _ => println!("{}", x),
}

use in patterns also lets you use ranges in patterns:

let x: (Option<RangeFull>,) = (Some(..),);
match x {
    (Some(use ..),) => println!("got rangefull"),
    _ => println!("no rangefull")
}
@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Dec 29, 2017
@Centril
Copy link
Contributor

Centril commented Dec 29, 2017

Can you clarify the semantics of use? It is not obvious to me what it does. Does use y entail a check that x == y ? If so, the keyword is a bad choice since it doesn't convey that intent clearly.

@SoniEx2
Copy link
Author

SoniEx2 commented Dec 29, 2017

"use the value of y here" or "use y" for short.

Or we could break every program and go with "let z" instead? I'm ok with that too, but it would break every program.

@mfarrugi
Copy link

This looks like syntax sugar for match guards.

fn main() {
    let x = 2;
    let y = 2;
    match x {
        _ if x == y => println!("{} {}", x, y),
        z => println!("{} {} {}", x, y, z)
    }
}

It seems unnecessary for these small examples.

@SoniEx2
Copy link
Author

SoniEx2 commented Dec 30, 2017

@mfarrugi Kinda, yeah, but it follows the DRY principle (don't repeat yourself), so it's much nicer to work with. (unless you propose we always use match guards as a way to solve the context-sensitivity issue? doesn't seem like a nice solution, tho)

@sinkuu
Copy link
Contributor

sinkuu commented Dec 30, 2017

(I removed the comment ("Rust has lint for that" or something) you are referring, before seeing your reply, as I noticed you are not concerned in such a way. Sorry for impeding discussion!)

@pnkfelix pnkfelix changed the title "Use" in patterns "Use" in patterns (to match an expression’s value) Dec 30, 2017
@Manishearth
Copy link
Member

@SoniEx2 Moderator Note Please be constructive.

I've noticed a pattern of you posting low-effort feature requests with little to no justification given, and then being incredibly blunt and unconstructive in the ensuing discussion.

Please act civilly in Rust spaces.

If you want to work with others to come up with actionable proposals I suggest discussing stuff in http://internals.rust-lang.org/ instead of here.

@SoniEx2
Copy link
Author

SoniEx2 commented Dec 30, 2017

Well, you haven't seen me act non-civilly, even if I may be using caps for emphasis.

And yeah, the original proposal - using an expression's value in a pattern - is surprisingly not something I care so much about, now. I care more about the context-sensitivity issue. The original proposal is one fix, there are other fixes like requiring pattern guards when using values (unless they're literals) and requiring all const to be all-uppercase and all non-const (yes, even static variables) to be non-all-uppercase.

There's no nice way to fix this except for some workarounds. (At least with the original proposal you can require that any match using at least one "use" must use "use" for every case, so it is a pretty good workaround if I can say so myself. We can then work towards deprecating the old syntax.)

@pnkfelix
Copy link
Member

Well, you haven't seen me act non-civilly, even if I may be using caps for emphasis.

Moderator Note: We have markdown available, so there's no need to use capitalization for emphasis.

If you are not already aware, use of all-caps is commonly equated with "shouting and other impolite or argumentative behaviors." As a fellow moderator, I think @Manishearth's note was warranted, if only to discourage future use of all-caps.

@pnkfelix
Copy link
Member

By the way, I don't wish to litigate the original note on thread. I just wanted to make a public service announcement regarding markdown and use of all-caps.

If you want more feedback on the details of @Manishearth's note, I recommend you email [email protected]

@Manishearth
Copy link
Member

Manishearth commented Dec 30, 2017 via email

@SoniEx2
Copy link
Author

SoniEx2 commented Dec 30, 2017

Rust 2.0 could fix this. I'd prefer let syntax for patterns, altho it might clash (or be weird) with if let?

if let Some(let x) = v hmm...

There's also the issue of whether it's destructuring or using a value...

match v {
  let Some(let x) => ...,
  None => ...,
}

// or

match v {
  Some(let x) => ...,
  None => ...,
}

I think use is probably the best syntax for this...

(If you meant "not" instead of "now", the issue is that the same token in the exact same place can mean either a value (often referred as "RHS") or a name (or "LHS"), and it can change even in the same file, so you can have a file where the same block of code appears twice, but on the first block it's a name and on the second block it's a value. This is especially annoying when you want your syntax highlighter to highlight the two cases differently, because it can't know which case it is. Maybe I'm weird but I'd like my syntax highlighter to tell me when I'm binding new names (or shadowing other names) without needing full static analysis.)

@scottmcm
Copy link
Member

Consider, in the title of the issue, whether the important part is use or explicitly distinguishing bindings from constants.

Perhaps braces might make sense here, similar to how they're used to pass a const expression as an explicit parameter to a generic? https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#applying-a-const-as-a-parameter

(An eventual epoch could even switch all unbraced idents to meaning bindings, though I'm sure that would be controversial for some time.)

@SoniEx2
Copy link
Author

SoniEx2 commented Jan 11, 2018

I'm not talking about changing constants to be different from identifiers.

I'm talking about making it clear when you're declaring new bindings.

We have let. Things would be confusing without let. Why then does match not follow the same rules?

(Having use for both constants and non-constants, and requiring it for both, makes things less confusing.)

@SoniEx2
Copy link
Author

SoniEx2 commented Apr 7, 2018

use range:

let x: (Option<RangeFull>,) = (Some(..),);
match x {
    (Some(use ..),) => println!("got rangefull"),
    _ => println!("no rangefull")
}

@Centril
Copy link
Contributor

Centril commented Oct 9, 2018

Closing in favor of #263.

@Centril Centril closed this as completed Oct 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

7 participants