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

Add if-while-let_multiple_patterns RFC #937

Closed
wants to merge 5 commits into from

Conversation

Munksgaard
Copy link

This has already been implemented in rust-lang/rust#23034

@Munksgaard
Copy link
Author

cc @Manishearth, @pcwalton

@laumann
Copy link

laumann commented Mar 4, 2015

Rendered

@Munksgaard
Copy link
Author

Discussed in #935

@Gankra
Copy link
Contributor

Gankra commented Mar 4, 2015

Should this RFC also propose that exhaustive normal lets should also work? It seems like that's the last place where | wouldn't work, which is sort of random.

e.g.

fn main() {
    let x: Result<u32, u32> = Ok(1);
    let Ok(y) | Err(y) = x;
    println!("{}", y);
}

@Kimundi
Copy link
Member

Kimundi commented Mar 4, 2015

@gankro: I agree that that would be more consistent, but I think that would make more sense to open as a seperate RFC.

Alternatively, a RFC could change PAT | PAT in general to become a pattern, which would make both ìf let, while let, let and function arguments be able to use the | form.

@Munksgaard
Copy link
Author

@Kimundi: The more general approach (eg. also allowing alternations (|) in function arguments) has been discussed a bit in #99.

I hadn't considered alternations in normal lets, but I guess we could create another RFC for that case?

@Manishearth
Copy link
Member

I would opt for a separate RfC for that.

@Manishearth
Copy link
Member

(I agree with this RfC, btw)

@glaebhoerl
Copy link
Contributor

We could consider extending if let and while let to also include guards, but that has opens up the question about syntax (if let Some(n) = x if n > 0 is not extremely pretty), so we should probably save that for an RFC of its own.

In fact if we also use if let as the syntax for Haskell-style pattern guards (which I think would be logical), then it seems like we could end up with if let Some(b) = a if let Some(c) = b, which is even more awesome, in a very particular sense. (This seems to also be an infinite regress?)

@pcwalton
Copy link
Contributor

pcwalton commented Mar 5, 2015

@glaebhoerl Couldn't all of those be written with @ (e.g. if let Some(b @ Some(c)) = a?

@glaebhoerl
Copy link
Contributor

@pcwalton Sure; I only meant to point out that if we change the if let expression to allow guards, and also generalize guards to allow pattern guards, also with the syntax if let, then as their interaction, a pattern guard on an if let would result in if let ... if let. (And, I think, you would be able to chain them arbitrarily.) This actually feels logical to me, but could also be considered unusual. The example was just to illustrate the syntax. (Tl;dr this is not at all meant to be taken as an objection on my part, just an observation.)

@Munksgaard
Copy link
Author

In fact if we also use if let as the syntax for Haskell-style pattern guards (which I think would be logical), then it seems like we could end up with if let Some(b) = a if let Some(c) = b, which is even more awesome, in a very particular sense. (This seems to also be an infinite regress?)

That's a very interesting question, and it doesn't seem like it would hurt the language as such. However, this seems like an orthogonal issue.

@Munksgaard
Copy link
Author

What's the verdict on this? Most people here and in #935 seem to be in agreement that this is a useful addition to the language, but it also opens up various questions regarding additional constructs such as nested if lets and guards. Most of those questions/suggestions represent larger additions to the language, whereas I feel like the feature proposed in this particular RFC has a more straightforward implication.

@brson
Copy link
Contributor

brson commented Mar 12, 2015

@Munksgaard my inclination is that this is a nice-to-have feature that we don't need presently. It's very tempting to add to Rust every nice convenience, but we have to exercise restraint.

@brson brson self-assigned this Mar 12, 2015
@lilyball
Copy link
Contributor

I'm not convinced that this is something we should do. In general, I'm in favor of making if let more powerful, but I'm concerned that making changes like this right now will prevent us from doing other useful stuff in the future.

For example, if let was inspired by Swift, and Swift 1.2 extends if let with some useful functionality that we don't currently have an analogue for in Rust, which is basically chained expressions. In Swift 1.2 you can say something like:

if let a = foo(), let b = a.bar(), let c = b.baz() where c > 2, let d = c.quux() {
    // do something with d
} else {
    // some expression in that chain failed
}

(this can actually be shortened slightly by dropping the 2nd and 3rd lets, it's only required on chained expressions after a where clause)

This is equivalent to

var success = false
if let a = foo() {
    if let b = a.bar() {
        if let c = b.baz() where c > 2 {
            if let d = c.quux() {
                success = true
                // do something with d
            }
        }
    }
}
if !success {
    // some expression in that chain failed
}

This turns out to be a useful construct, and I'd like to eventually get something similar into Rust. But if we loosen the if let syntax today, it's not clear if that will interfere with the ability to extend the syntax like this in the future.

More generally, making changes to make if let be able to do more stuff that match can do just seems like something being done for the sake of doing it. If you want to do stuff that match can do, then go ahead and use match. if let today is just a convenience for a simple form of match, but there's no reason why it needs to be equivalent to a single match in the future.

@mdinger
Copy link
Contributor

mdinger commented Mar 16, 2015

@kballard That seems similar to #929 which used && instead of commas, though where clauses never occurred to me.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 16, 2015

For example, if let was inspired by Swift

That is not true. The idea of if let was circulated in the /mozilla/rust issue tracker long before Swift was announced.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 16, 2015

rust-lang/rust#1529

Credit goes to @kevina

@lilyball
Copy link
Contributor

@mahkoh I wrote the if let RFC. It was directly inspired by Swift. Similar concepts may have existed before (such as rust-lang/rust#1529) but were not part of the design of our current if let.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 16, 2015

That just means that the RFC was inspired by swift. The idea to destructure in if is much older. It might even be so that someone working on swift got the idea from the linked issue.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 16, 2015

To contribute something on-topic: I share @kballard's concerns. The following constructs seem interesting too and one would have to think about how they interact with this RFC:

if let Some(x) = x1 || let Some(x) = x2
if (let Some(ref x) = x1 && x > 0) || let Some(ref x) = x2

@brson
Copy link
Contributor

brson commented Apr 6, 2015

Although this is a cool feature, per general concerns about feature creep, I'm closing this RFC without accepting it. Thank you.

@brson brson closed this Apr 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet