The features/patterns
branch needs to be split into two branches for those features we are reasonably certain will be in C# 7 and those features that might be delivered in a later release. The former can be integrated into the future
branch and the latter can remain in the patterns/feature
branch.
Part 1 (targeting future
):
expression is Type identifier
case Pattern when expression:
with the following pattern formsPart 2 (to remain in features/patterns
):
*
let
statementmatch
expressionthrow
expressionNo!!! Please don't leave match
expression out of the C# 7 release!
With all the experiments I've done so far with patterns, I've probably used match
90% of the time and switch
only 10%; if that much. Pattern matching is a functional feature and functional programming is all about expressions; not statements. Having pattern matching only in switch
would be a weird addition to C# that I'd imagine most functional-style C# developers would just ignore and most OO-centric developers will just not understand or use. It would be a hugely wasted opportunity. If match
can't make it into C# 7, then there's no point in releasing pattern matching at all in that release, IMO.
I think it makes more sense to also postpone var patterns because without recursive patterns there ain't no real use for var patterns alone. Honestly, I think the team could deliver a more sophisticated value binding pattern overall, but shipping var patterns would close that case right away. :(
@DavidArno Your feedback on the prototype that results from these changes will be helpful in our planning.
@alrz A var pattern is useful as the last case of a switch statement. I'm not sure what you have in mind with a "value binding pattern".
@gafter,
I'm not sure that my feedback will change from now. It's difficult to articulate the frustration and sadness I feel over the Remove evidence of advanced pattern-matching features for C# 7
commit. But I'll have a go...
As someone who uses C# to write functional-orientated code, the experience is a difficult one. A lot of the time, I seem to fight the language, rather than working with it. So when I first came to this site and saw the list of features that potentially might make it into C# 7, I was extremely excited: tuples, records, pattern matching were all up there at the top of the list. These were exactly the sort of features that I wanted added to the language. Exciting times lay ahead.
Since then, I've seen things steadily go downhill:
switch
will likely be offered; but I don't use switch
, so this has no value to me.is Type var
feature looks like it will make it in to the next release, but since "pattern-matching based on user-defined code" won't, that suggests custom is
operators won't be supported. Thus this becomes a minor syntax improvement feature; rather than a pattern matching one. Useful, but hardly exciting.let
keyword, supplying immutable vars, won't make it in C# 7, and I suspect the "never make breaking changes, ever!" camp will win on this and it never will make it in to the language.What we will likely get are:
out var
support. out
parameters are an anti-pattern in my world. Making it easier to use this anti-pattern isn't therefore a feature I'm going to get excited about, other than in a negative sense.is
operators, there seems little point in creating those work-arounds. So again another feature I don't care about.C# 7 started out appearing to be a super exciting release: "C# gets functional". Now though it's appearing to be a complete "meh" release. I'm sure some (maybe even the majority) will be excited by the likely new features, but even the features that do interest me (tuples and local functions) are disappointingly poor implementations of what I'd really like to have seen.
More and more devs are catching the "functional bug". In the .NET world, this normally means switching to F#. Whilst a great language, it's not without its problems, such as having nowhere near the level of tooling that C# devs enjoy. A few months ago, C# 7 looked like it could offer a great set of functional features too, giving people a choice. That dream is well and truly shattered now. Maybe C# 8 will deliver, but maybe it will prioritise other features I'm not interested in (eg private protected
- I don't use inheritance, so again a useless feature for me) over delivering real pattern matching, along with immutability, DU's, records etc. So that leaves me, and others in my position, with a frustrating choice: wait maybe another year or two in the hope the features we want appear in a future release, or give up on C# as a lost cause and move over to F#. Going from a high level of excitement to facing this choice over the course of a few months, has been a hugely sobering experience, sadly.
Having said all of that, I am aware that the language team have a difficult balancing act to contend with. They have conflicting demands from the majority who want more of the same and a minority who want radically new features in order to stay with the language. If you meet the needs of the former, you risk failing to stem the tide of leavers. If you meet the needs of the latter group, you risk complaints from the majority that you are pandering to a minority and ignoring what most want. Also, I accept that my "excitement to disappointment" experience is entirely of my own making. You guys have been very clear all along that nothing is set in stone and I've ignored that all along at my own cost. I've tried to offer honest feedback. If it comes across as negative criticism, I can only apologise as that isn't my intention.
@gafter In the current spec let x = e2 when e2 else stmt;
is not possible while let var x = e2 when e2 else stmt;
is. Unless you want to take breaking changes, allowing that would complicate the syntax for let
statements. I wrote up my thinking regarding value binding patterns in #10624 comment it doesn't allow let var x
and replaces var
with let
in patterns.
In that comment, you wrote
_identifier-pattern_ (has overlap with _constant-pattern_, see below)
But there is no hint "below" as to what a _constant-pattern_ is, or how the ambiguity would be resolved.
@gafter I could be more specific. That's nothing new though, Swift uses this semantics so I suppose it wouldn't be a problem, unless you see something that I don't.
switch(e) {
// x and y are constants as the current spec
case (x, y): break;
// x and y are new variables as the current spec (just `let` instead of `var`)
case (let x, let x): break;
// x and y are new variables (`let` distributes to each identifier pattern)
// -- short for the previous case
case let (x, y): break;
// this is not allowed due to the "value-binding patterns cannot be nested" rule
case let (let x, let y): break;
// so the following is perfectly fine,
// an identifier inside a value-binding pattern which introduces a variable
case let x: break;
}
This wouldn't be restricted to tuples and works for any other recursive patterns in the spec.
switch(e) {
case let Point(x, y): break;
// equivalent to
case Point(let x, let y): break;
case let Point { X: x, Y: y }: break;
// equivalent to
case Point { X: let x, Y: let y }: break;
}
This is specifically consistent with _let-statement_ as it is kind of a "value-binding pattern" so that wouldn't be much of a surprise and there is no need to special case let x = e
because you will get it "for free" via identifier patterns.
let x = e;
let (x, y) = e;
The production
pattern
: `let` pattern
;
doesn't makes sense to me. Is the idea that once you put let
before a pattern, you can't have constant patterns anywhere inside them?
This is now done. Part 1 is in future
, and Part 2 is in features/patterns
.
@gafter Non-identifier constants are fine, but identifiers will be new variables in presence of let
before the pattern. So you will have let (x, y, 1, "")
as a shorthand for (let x, let y, 1, "")
. There is nothing ambiguous about literals here.
You can't prevent the recursion syntactically, because you might have a let pattern anywhere inside it anyway. So it has to be done semantically.
I would like to add that match
is already the most used C# 7 feature for me as well, about tied up with the new switch
(I've utilized both extensively, I always just use the new features for hobby-projects wherever they make sense, then modify the code when VS drops support).
I've had my own libraries for _"pattern matching"_ previously, but having the feature actually incorporated in the language results in far-higher quality code than any implementation I could think of using only existing features.
It won't be _that_ horrible to emulate with switch
I guess, but drops the opportunity to use pattern matching in expression bodied methods, where match
often makes the most sense now.
does this split have any implications for exhaustiveness checking in switch/match?
does this split have any implications for exhaustiveness checking in switch/match?
No. switch
does not currently do exhaustiveness checking, and we do not expect to change that. match
isn't part of the C# 7 side of the split, so there is nothing there to report.
If match
will not be in C# 7 does this mean I have to use a statement to match values? E.g.
int someResult;
switch (input) {
case ...: someResult = 123; break;
...
}
That is so awkward that even nested ?: are better. Also, it can't be a subexpression.
var someResult =
someCase ? 1234 :
someOtherCase ? 5678 :
...;
This code is clean but tooling support is notoriously bad for that pattern.
Can we not have a form of match
that only supports what's uncontroversial (e.g. what switch does but as an expression). Expressions compose so much better than statements. switch
in C was meant as a way to make the compiler generate jump tables (e.g. Duffs Device). It never was meant to do this rather extensive job.
I'm pretty sure that match
is not totally discarded, it's just postponed for a later version.
I understand that and it's a cause for great sadness!
Is the list below "What we will likely get are" in this thread exhaustive? That would be like C# 4 in significance which was the least significant release so far.
@GSPP Check out #2136.
Most helpful comment
No!!! Please don't leave
match
expression out of the C# 7 release!With all the experiments I've done so far with patterns, I've probably used
match
90% of the time andswitch
only 10%; if that much. Pattern matching is a functional feature and functional programming is all about expressions; not statements. Having pattern matching only inswitch
would be a weird addition to C# that I'd imagine most functional-style C# developers would just ignore and most OO-centric developers will just not understand or use. It would be a hugely wasted opportunity. Ifmatch
can't make it into C# 7, then there's no point in releasing pattern matching at all in that release, IMO.