3 ms·
I think switch could have been made into an expression very easily by following the lead of lambdas and method-body expressions, namely the => arrow. var a
by louthy 10y ago
I think switch could have been made into an expression very easily by following the lead of lambdas and method-body expressions, namely the => arrow.
var area = switch
(
case Line l => 0;
case Rectangle r => r.Width * r.Height;
case Circle c => Math.PI * c.Radius * c.Radius;
default: throw new ApplicationException();
)
That 'feels' to me to be consistent with the expression approach taken elsewhere, whilst making it clear to anybody used to seeing the statement based switch that it's different.
> so the pattern matching overall is way less useful to me without records/discriminated unions.
I agree partially. I think it's possible (I'll investigate tomorrow) to provide an 'is' operator override. So for example in my implementation of Option<T> [1] (which would usually be a sum-type of Some(x) and None, I instead use a struct (to remove a 3rd state of null).
With the 'is' operator I'm hoping to do this:
public static class Some
{
public static bool operator is(Option<T> option, out T value)
{
value = option.Value; // Value is internal
return option.IsSome;
}
}
switch(option)
{
case Some x: ...; break;
default: ...; break;
}
I'm not sure if I can do this:
public static class None
{
public static bool operator is(Option<T> option)
{
return option.IsNone;
}
}
switch(option)
{
case Some x: ...; break;
case None: ...; break;
}
So although it doesn't solve the general need for sum-types and record-types, it should hopefully facilitate some of the common use cases.
Agreed about ref and out; I understand their purpose, I just despise them with a passion. Their whole syntax and ickyness makes me feel queesy. The inline var out feels like an imbalanced expression. They're clearly more useful now, but they still feel odd.
[1] https://github.com/louthy/language-ext/blob/master/LanguageExt.Core/Option.cs#L24 https://github.com/louthy/language-ext/blob/master/LanguageE...
- Locke1689 10y agoRegarding switch-as-expression -- the semantics of pattern matching as an expression can be subtle, especially when paired with nullability, so I think there's more support for introducing a new "match" expression that does what you describe. Switch is more of an effort to integrate patterns in the way C# is used right now.
- louthy 10y ago> the semantics of pattern matching as an expression can be subtle, especially when paired with nullability Could you expand upon that? If I can do this: var area = shape is Line l ? 0 : shape is Rectangle r ? r.Width * r.Height : shape is Circle c ? Math.PI * c.Radius * c.Radius : throw new ApplicationException(); How is this, a collection of predicates and expressions, not the same? var area = switch(shape) { case Line l => 0; case Rectangle r => r.Width * r.Height; case Circle c => Math.PI * c.Radius * c.Radius; default => throw new ApplicationException(); } I realise you work on Roslyn (and you said semantics, so my example may be a bit off), so I'd love the detail on why the above is problematic.
- Locke1689 10y agoWell, let's say Line, Rectangle, and Circle are reference types. Which case does null match? If you match the first type, that's somewhat unsatisfying. But if you only match with default, that's also unsatisfying because now we would have a problem with completeness -- if the match doesn't succeed then you have a potentially unassigned variable. So now every match expression would have to have a default case just to handle null, but you also don't gain the advantages of static matching because everything matches default, so if you do legitimately forget a case you get no warning. Existing switch statements are much more resilient to these matters simply because they aren't expected to be exhaustive right now. People are used to the fact that they have to deal with unassigned variables or completeness failures. The match expression, however, I want to be more like ML where you can get strong guarantees on the "irrefutability" of a match.
- louthy 10y ago> Well, let's say Line, Rectangle, and Circle are reference types. > Which case does null match? None of them, it should be a case on its own: var area = switch(shape) { case Line l => 0; case Rectangle r => r.Width * r.Height; case Circle c => Math.PI * c.Radius * c.Radius; case null => throw new ArgumentNullException(); } That would allow for completeness checking, and if you do want a catch-all then you'd add a default clause. I have since looked at the proposal for the expression based switch. TBH, I'll just be happy when it's in the language, the syntax is less important to me; but I am not quite sure it needed such a drastic change - it does feel a touch awkward. > The match expression, however, I want to be more like ML where you can get strong guarantees on the "irrefutability" of a match. Music to my ears.
- int_19h 10y agoTake a look at the "match expression" section here. https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md https://github.com/dotnet/roslyn/blob/future/docs/features/p...