C# has seen a similar push to implement pattern matching, down to the use of `_` as discard. The first iteration of this feature in C# 7 is feature light, but it's a good start, and they've promised more to come. The team behind C# has become really good at getting over NIH and embracing new technologies and techniques while somehow preserving backwards compatibility and ergonomics. Anders Hejlsberg doesn't kid around.
Here's an example cribbed from an official MSFT blog [0]:
public static int Count<T>(this IEnumerable<T> e)
{
switch (e)
{
case ICollection<T> c: return c.Count;
case IReadOnlyCollection<T> c: return c.Count;
// Matches concurrent collections
case IProducerConsumerCollection<T> pc: return pc.Count;
// Matches if e is not null
case IEnumerable<T> _: return e.Count();
// Default case is handled when e is null
default: return 0;
}
}
A lot of people have lamented this as the death of F#, but I think MSFT is making the right calls here.EDIT:
Little-known fact: C# actually does have discriminated unions, and has had for a long time (from the start?) in the form of the `Exception` base class. In fact, pattern matching in C# can be "pulled off" (read: hacked together as a proof-of-concept) without the changes from C# 7 by simply using the extended catch syntax:
class MyType1 : System.Exception
{ /* ... */ }
class MyType2 : System.Exception
{ /* ... */ }
void foo()
{
throw something ? new MyType1() : new MyType2();
}
void bar()
{
try
{
foo()
}
catch (MyType1 mtype)
{
//take type-specific action here
}
catch (MyType2 mtype)
{
//take type-specific action here
}
catch (Exception _)
{
//the _ was optional, but this is the `default` block
}
}
[0]: https://blogs.msdn.microsoft.com/seteplia/2017/10/16/dissect...