3 ms·
Wouldn't the OP get the same result by staying in C# and changing the outer if-else to a switch? I'm not super familiar with C#, but many C++ and Java compiler
by BruceIV 12y ago
Wouldn't the OP get the same result by staying in C# and changing the outer if-else to a switch? I'm not super familiar with C#, but many C++ and Java compilers do that. (Pattern matching is still a cool feature, as some of his later examples show, I just don't think his first one motivates it.)
- radicalbyte 12y agoYes, I'd never let his outer if-else get through code review. Visual Studio even has special support for generating a correct switch statement (all values + default) for enums. Still, I'd love to have first-class pattern matching in C# and of course algebraic data types...
- JackMorgan 12y agoThe correctly generated switch case isn't the point. It's not that it can't be generated the first time, it's that it can't detect the accuracy of the switch case every time there is an edit. Also, the enum in a switch is the least powerful thing F#'s pattern matching gives you. Consider the second to last example, where I turn three nested switch statements into a single match. Now the compiler checks on the _combination_ of those three for anything missing. That is far more powerful than any static analysis tool I've seen can detect. Think, any time you need polymorphism, instead of reaching for classes and interfaces, you can just have a "combined" match that not only checks that you have all the types, but that the conditional work each type was doing is "all there". That's some powerful stuff. What that leads to is the inverse of traditional polymorphism, now the "behavior" for a type can reside where it's needed, all together right where used. Not only is this safer, but it's much more likely to be the axis on which it will change. In my experience, the traditional interface and class polymorphism changes in such a way that I need to edit every class. Usually, it's an extra parameter one class needs, or a different return type. Changes like that mean editing every subclass. Instead, if I used "match" for my polymorphism, those changes would just be all together, next to each other. What you lose with this inverted polymorphism is you no longer have a single place to see all the behavior for a single type. We've changed the grain of how the type is used to run such that seeing the behavior for a single function for all types is possible, but seeing all the functions for a single subclass requires going to several classes. The good news here is _you can choose which style you want for every single function_. You can even have this function be a match on the type in place, while this other lives on the subclass! Now you can choose the best axis based off the likely change pattern. Going to be changing the interface a lot? Make it a match. Going to be only changing the internals of a single subclass a lot? Put it in the interface. And it's easy to change one to the other, so you don't even have to get it right the first time! That being the case, and seeing how powerful the match is at detecting missing edge cases, I'd suggest always start with match for polymorphism, then convert to an interface method when needed.