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

Pattern matching that supports equality #1059

Closed
CaseyLeask opened this issue Apr 12, 2015 · 10 comments
Closed

Pattern matching that supports equality #1059

CaseyLeask opened this issue Apr 12, 2015 · 10 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@CaseyLeask
Copy link

Hi all,

I was going through http://rustbyexample.com/flow_control/match/guard.html

fn main() {
    let pair = (2, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {:?}", pair);
    match pair {
        (x, y) if x == y => println!("These are twins"),
        // The ^ `if condition` part is a guard
        (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
        (x, _) if x % 2 == 1 => println!("The first one is odd"),
        _ => println!("No correlation..."),
    }
}

and I tried to do https://gist.github.com/CaseyLeask/89d85dd213c618dac58d#file-guard-rs-L7 .

fn main() {
    let pair = (2, -2);
    // TODO ^ Try different values for `pair`

    println!("Tell me about {:?}", pair);
    match pair {
        (x, x) => println!("These are twins"),
        // The ^ `if condition` part is a guard
        (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
        (x, _) if x % 2 == 1 => println!("The first one is odd"),
        _ => println!("No correlation..."),
    }
}

Is there a reason that this wouldn't be desirable?

Cheers,
Casey

@CaseyLeask
Copy link
Author

Sorry if this is a duplicate, but I couldn't find this question in either the rust or rfc issues.

@ghost
Copy link

ghost commented Apr 13, 2015

Other languages which have pattern matching don't allow this.

In Haskell, this code doesn't compile:

f x x = 1
f x y = 0

But this code does

f x y | x == y = 1
      | otherwise = 0

IMO, pattern matching should be a form of destructuring, not running functions like equality, so, I don't think that this is a good feature to add.

@CaseyLeask
Copy link
Author

@Undeterminant As a counterexample to that, Erlang is another language which does.

-module(equality).
-export([eq/2]).

eq(X, X) -> true;
eq(_, _) -> false.

Since we're talking about pattern matching, I think equality is a pattern that could be detected.

@Kimundi
Copy link
Member

Kimundi commented Apr 13, 2015

The issue with supporting equality in patterns in general is that its ambitious what kind of equality is meant - Does it require a Eq or PartialEq implementation, or does it use its own definition of structural equality?

@nagisa
Copy link
Member

nagisa commented Apr 13, 2015

This requires special casing _ even more, because eq a a = True and eq _ _ = True are α-equivalent.

I prefer the current, shadowing behaviour.

@quantheory
Copy link
Contributor

I would argue that no pattern without a guard should ever desugar to a pattern with a guard, because patterns with a guard do not influence exhaustiveness checks and reachability checks for later match arms. That is, Foo(x, x) and Foo(x, y) if x == y are not semantically equivalent, because the former must involve a "structural" constraint that influences the various match checks, whereas the latter is forbidden from being anything but a run-time check.

(Full disclaimer: I have a draft RFC on the "in a month or two" horizon that depends on this sort of distinction, because it proposes using match patterns to influence coherence checks involving dependent types.)

That's not necessarily an argument against allowing Foo(x, x). Rather, I'm saying that if we do allow such a thing, it needs to be with the understanding that it is actually adding a constraint that the compiler needs to track. I.e., if a match pattern uses Foo(x, x), then a later pattern that uses something like Foo(None, None) in the same position should be considered unreachable.

@bfops
Copy link

bfops commented Nov 19, 2015

I am strongly against implementing this. As said above, this generates a very subtle (and possibly expensive) equality check. Maybe this could make sense when restricted to Copy types, but I really don't see an issue with using a match guard. I also don't really think this is unambiguous enough for the behavior to be obvious: if I saw a pattern like this, I might suspect that it tested, but not with anything close to certainty, which means it's not only another language feature to implement, but also another language feature to explain. It doesn't seem like a very common use case to me, and the cost of not having this feature is low, even when that use case comes up, so I'm strongly in favor of keeping the language simpler.

@petrochenkov petrochenkov added the T-lang Relevant to the language team, which will review and decide on the RFC. label Jan 30, 2018
@Centril
Copy link
Contributor

Centril commented Oct 7, 2018

Closing in favor of tracking issue #1059.

@Centril Centril closed this as completed Oct 7, 2018
@golddranks
Copy link

@Centril your link seems to be wrong, it points to this same issue.

@Centril
Copy link
Contributor

Centril commented Oct 7, 2018

Apparently I need some sleep...
I meant to link it to: #263.

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

8 participants