-
Notifications
You must be signed in to change notification settings - Fork 4k
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: expression-based switch ("match") for pattern matching #5154
Comments
Does this mean that there won't be an expression match statement? |
Feels linqy to me, with an infix keyword and no explicit terminators: var areas =
from primitive in primitives
let area = primitive match {
case Line l => 0
case Rectangle r => r.Width * r.Height
case Circle c => Math.PI * c.Radius * c.Radius
default => throw new ApplicationException()
}
select new { Primitive = primitive, Area = area }; Will the absence of clause terminators cause any problems? I can't think of any cases, since |
If I understand that sentence correctly, it means that it's the only place in the language (except
Does this proposal include a better way to find the common type?
And finally, how are variables from patterns scoped: can we reuse the same variable name for two different patterns in the same match expression? |
Since a case guard is an expression, it can't introduce a variable. If the same expression is needed both in the guard and in the result, it has to be executed twice. Consider the following example:
Ideally |
@MrJul, I suppose that would be something like this:
|
@paulomorgado There is no
There is no proposed |
You already cannot make that transformation in expression-boded methods. Programmers already introduce their temporary variables before a statement that needs it, and things get awkward in contexts, such as a ctor-initializer, where there is no statement list into which such a local declaration can be placed. This construct is not intended to address that issue.
No, the proposal does not modify the best-common-type specification. Your example would be a compile-time error that is easy to fix.
Yes. Please see the first sentence in the "Semantics" section. |
It felt very strange when I wrote it! Looks like pattern matching is not allowed on So, other than being an expression what differs |
@paulomorgado the |
Nitpicking: Wouldn't |
I think of this as similar to the linq |
Nice. So is there so separator between cases? It feels a little weird that |
Continuing on @HaloFour's thoughts on Suppose that there is no default case, and |
Perhaps there should be a comma between cases. I've changed the syntax to require that. Using |
@orthoxerox's example is now var areas =
from primitive in primitives
let area = primitive match {
case Line l => 0,
case Rectangle r => r.Width * r.Height,
case Circle c => Math.PI * c.Radius * c.Radius,
case * => throw new ApplicationException()
}
select new { Primitive = primitive, Area = area }; |
This would be nice with declaration expressions, too. object x = "123";
int y = x match {
case int i => i,
case string s where int.TryParse(s, out int i) => i,
case * => throw new ApplicationException()
}; |
@HaloFour: IIRC (not sure I'm remembering this correctly - there've been many discussions on pattern matching), this is an use case for a custom |
@SolalPirelli Yes, the current spec supports that, but not using the syntax you provided: class ParsedInt
{
public static bool operator is(string s, out int i) => int.TryParse(s, out int i);
}
...
"42" match { case ParsedInt(int i) => i, ... |
Why not use the exist syntax of named parameters? for introducing variables within the object x = "123";
int y = match( x )
{
|: (byte) => 0;
|: (i: int) => i;
|: (s: string) when int.TryParse(s, out int i) => i;
|: * => throw new ApplicationException();
}; |
@gafter As others have said I do think that the when keyword would be more appropriate for guards for two reasons:
@HaloFour @AdamSpeight2008 |
An alternative for |
|
@aluanhaddad I'm not mixing value and types, since a matching against a type is likely a common match pattern. |
This issue does not propose any syntax for patterns. That is specified in #206. But the short answer is that these are more akin to parameter declarations than they are to named arguments. |
@alrz the comma is coming back. |
@gafter That is not great. Just because of |
@alrz sigh |
@gafter Actually, when I think about it, that was really helpful. |
LOL 😆 |
Lets see how it works out without adding new keywords. That option remains open if it appears preferable after trying this version. |
Using |
I wish you guys would focus on semantics instead of syntax. I wouldn't care if zombodash was the chosen keyword; what matters is the semantics. Every language that supports pattern matching (and not just destructuring.. even ES6/Javascript has destructuring) does it slightly differently and leads different benefits and pains. Can you explain what those tradeoffs are, where we sit in that spectrum, and justify the decision? What kinds of tests will pass fail under what asumptions, what is an error, warning etc.. |
@jonschoning I'd say |
The syntax is the easiest aspect to adjust based on experience. |
@gafter Isn't it proposed that case-expression would be part of statement-expression so that |
@alrz that form is proposed to require that the match can be proven to always succeed. |
@jonschoning 👍 I'm inclined to declare this a "semantics-only" thread from now on. Syntax is easy. I can test 100 syntax changes a day. Semantics requires binding work and forethought, both of which are hard. |
Reading the latest spec, am I correct that throw throw throw null; Would now be a legal expression in some contexts? |
@agocke No. The spec says
"the operand of |
@gafter I see, thanks. |
This has been folded into the pattern matching spec. |
Link to documentation https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md is broken. I guess it should be https://github.com/dotnet/csharplang/blob/master/proposals/patterns.md |
The spec has been moved
The spec for the proposed match expression has been moved to https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md
Below is a snapshot that may be out of date.
Match Expression
A match-expression is added to support
switch
-like semantics for an expression context.The C# language syntax is augmented with the following syntactic productions:
relational-expression : match-expression ;
We add the match-expression as a new kind of relational-expression.
At least one match-section is required.
The match-expression is not allowed as an expression-statement.
The type of the match-expression is the least common type of the expressions appearing to the right of the
:
tokens of the _match section_s.It is an error if the compiler can prove (using a set of techniques that has not yet been specified) that some match-section's pattern cannot affect the result because some previous pattern will always match.
At runtime, the result of the match-expression is the value of the expression of the first match-section for which the expression on the left-hand-side of the match-expression matches the match-section's pattern, and for which the case-guard of the match-section, if present, evaluates to
true
.The text was updated successfully, but these errors were encountered: