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

Proposal: Negative Pattern #246

Closed
alrz opened this issue Mar 10, 2017 · 17 comments
Closed

Proposal: Negative Pattern #246

alrz opened this issue Mar 10, 2017 · 17 comments

Comments

@alrz
Copy link
Contributor

alrz commented Mar 10, 2017

Copied from: dotnet/roslyn#16766

Negative Pattern

I propose to add a pattern operator to negate the effect of another pattern,

not-pattern:
not pattern

A "negative pattern" could be applied to an arbitrary pattern and reverse the failure path.

Examples:

if (obj is not null)

switch (obj) {
  case not Constant:
      break;
}

It could be even nested in recursive patterns as well,

case (not 0, var y):
// equivalent to
case (var x, var y) when x != 0:

This would be consistent with other proposed pattern operators like #118.

Definitive assignment rules are reversed, for example,

if (obj is not T t) return;
// t is definitely assigned

This also eliminates the need to parenthesize the is expression in case you want to negate the result.

Note that negating a simple type check requires a discard since is and recursive patterns have different binding precedence.

if (o is Foo) {}
if (o is not Foo _) {}
@gafter
Copy link
Member

gafter commented Mar 10, 2017

Definitive assignment rules are reversed

Really? How would that work for recursive patterns?

@alrz
Copy link
Contributor Author

alrz commented Mar 10, 2017

@gafter

Perhaps this would be only useful as a top-level pattern in if statement if there is a pattern variable. My statement certainly wouldn't make sense for obj is X(not Foo foo, 1).

@gafter
Copy link
Member

gafter commented Mar 10, 2017

Perhaps this would be only useful as a top-level pattern in if statement if there is a pattern variable. My statement certainly wouldn't make sense for obj is X(not Foo foo, 1).

In that case this seems like an awful lot of language baggage for something you can already express with if (!(e is P)).

@Kaelum
Copy link

Kaelum commented Mar 15, 2017

!is or is!

@alrz
Copy link
Contributor Author

alrz commented Mar 15, 2017

@Kaelum

that's #27. Regarding definite assignment, I think that proposal is more straightforward to implement.

@ivankarpey
Copy link

ivankarpey commented Oct 24, 2018

I personally feel like having not operator as alias or synonym for ! could be a good improvement. This operator alone could improve could readability a lot and save dozens of hours, because I feel like every developer just forgets about ! often and it's not super easy to identify this since it's only one symbol.

@gafter
Copy link
Member

gafter commented Oct 24, 2018

@ivankarpey I think you're confusing expressions and patterns. The proposal is that not pattern would be a pattern. It is already the case that ! expression is an expression. Since a constant expression can be a pattern, a different token has to be used for the two use cases.

    if (e is !true) // if e is false

    if (e is not true) // if e is anything other than true

@ivankarpey
Copy link

@gafter that make sense for a pattern matching cases with types for instance. But for bool value there anything other than true is the only false.

@HaloFour
Copy link
Contributor

@ivankarpey

The operand doesn't have to be bool. This is already legal:

object o = GetSomeRandomObject();
if (o is !true) {
    DoSomething();
}

And that means:

if (o is bool && (bool)o == false) {
    DoSomething();
}

But that would inherently behave differently to the not pattern which would negate the pattern completely, so that it applies even if o is not a bool:

if (o is not true) {
    DoSomething();
}

would mean:

if (!(o is bool && (bool)o)) {
    DoSomething();
}

That's why new syntax is necessary.

@ivankarpey
Copy link

ivankarpey commented Oct 25, 2018

@HaloFour the fact that !true is legal doesn't mean it's good. not true will be looking much more readable and clear. You all guys don't understand my concern. I don't have anything against negative pattern matching, I'm just saying that having 'not' syntax will be much better even for a simple bool expression, not only pattern matching cases. But since there is no separate ticket for that instead of creating new one, I just add my comments to this one, since I decide it could be kind of relative

@HaloFour
Copy link
Contributor

HaloFour commented Oct 25, 2018

@ivankarpey

the fact that !true is legal doesn't mean it's good.

But it's legal and has been since C# 1.0, so it's not going anywhere.

not true will be looking much more readable and clear

Which is fine, but not has to behave differently here in order to appropriately handle negating patterns. It can't be a synonym for ! otherwise it loses all of the functionality necessary for this proposal to work.

This proposal isn't about adding keyword versions of existing C# operators. It's about creating additional patterns, including one that can negate. If it weren't for the fact that ! already creates that ambiguity there'd be no reason to add a different syntax.

@ufcpp
Copy link

ufcpp commented Oct 25, 2018

static void M(bool? b)
{
    if (b is true)
    {
        // b == true;
    }

    if (b is !true)
    {
        // b == !true
        // i.e. b == false
    }

    if (b is not true)
    {
        // b != true
        // i.e. b == false || b == null
    }
}

@HaloFour
Copy link
Contributor

@ufcpp

if (b is not true)
{
    // b != true
    // i.e. b == false || b == null || !(b is bool)
}

b could be an instance of string (or anything else) and it the pattern would match successfully. That's not the case with !true where b has to be a boolean of the value false to match successfully.

@yaakov-h
Copy link
Member

yaakov-h commented Oct 25, 2018

@HaloFour in this case, b was declared up the top of the snippet to be bool?. False or null are the only remaining cases that are not true.

@Kaelum
Copy link

Kaelum commented Oct 26, 2018

@HaloFour I understand the reasoning for adding the "not" keyword, but if "!is" became legal, then the keyword would no longer be needed, the syntax would be consistent with all other uses of the "!" symbol, and whitespace around it would not have any meaning. It may not look pretty, but this is a "C" based language, so it doesn't need to be. This is not Visual Basic; therefore, it doesn't need to read like "English", nor should it.

@HaloFour
Copy link
Contributor

@Kaelum

but if "!is" became legal, then the keyword would no longer be needed

Patterns can be applied in other places, though, not just with is. This is already the case with C# 7.x switch statements, and that is going to expand dramatically with C# 8.0 with recursive patterns and switch expressions. So a modifier to is wouldn't be sufficient as it couldn't negate patterns anywhere else.

@alrz
Copy link
Contributor Author

alrz commented Jan 7, 2020

Closing in favor of championed issue #1350

@alrz alrz closed this as completed Jan 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

7 participants