Programowanie

Pattern Matching dla biednych

Update: Pojawił się nowszy artykuł na ten temat.

 

W językach funkcyjnych istnieje coś takiego jak pattern matching (tłumaczone na “wyrażenie dopasowania” – brzmi okropnie). Generalizując to taki switch który w zależności od jakiegoś warunku, albo typu danego wyrażenia wykona zadaną operację.  Bardzo fajnie używa się go w F# (przykład z MSDN):

 

 

Ponieważ czegoś takiego brakowało mi w C# za symulowałem to działanie za pomocą… Dictionary. Żeby nie być gołosłowny to konkretny kod produkcyjny w naszej aplikacji wykorzystujący tego typu pattern matching:

Powyżej statyczna klasa, która zawiera w sobie Dictionary będące kontenerem na wyrażenia dopasowania. Po lewej stronie jako key używamy wzorca, a po prawej jako value używamy akcji która ma być wykonana.

 

Testowanie tego typu zachowania jest proste:

Testy w tym przypadku są bardzo ważne. Kompilator F# potrafi wychwycić kiedy w swoim pattern matchingu nie wychwytujesz wszystkich możliwości. Nasze rozwiązanie jest nasze, więc kompilator go nie wspiera. Testujemy je.

Poniżej produkcyjne użycie pattern matchingu:

Tak to funkcja Main aplikacji konsolowej – dzięki temu podejściu uproszczona. Wcześniej był tu zestaw ifów w których zawierały się ify i switche.

 

Słyszałem, że do C#7 mają dodać pattern matching w switchu… Ale ja za switche dziękuję tym postem.

 

Co myślicie o takim kodzie? Dzielcie się bo może czegoś się nauczę, a następnym razem postaram się pokazać jak to zrobić za pomocą dynamic. Bo wczoraj kolega mnie natchnął. Więc “natchnijmy” się wspólnie  – komentujcie! 🙂

5 thoughts on “Pattern Matching dla biednych

  1. Pingback: dotnetomaniak.pl
  2. Dla mnie nie do końca zrozumiała jest inicjalizacja Dictionary:
    [WhenAnalyze] = RunAnalyzer. Oznacza to, że key WhenAnalyze (który jest func) ma mieć value RunAnalyzer (czyli action)? Co robią te kwadratowe nawiasy?

  3. Dokładnie jak kolega napisał. Nie tłumaczę kodu dokładnie, bo art. jest raczej dla pokazania pomysłu, a używam C# 6 bo jest jeszcze bardziej zbliżony do funkcyjnego.

  4. Ja bym tu raczej użył custom klasy, tak żeby po prostu napisać:

    var matcher = Matcher
    .When(x => x.Length == 0).Do(x => Console.WriteLine(“empty”))
    .When(x => x.Length > 0).Do(x => x.ForEach(Console.WriteLine))
    .Build();

    matcher.Match(new[] { “foo”, “bar” });

    muszę to wypróbować w praktyce, dzięki za wpis

Leave a Reply

Your email address will not be published. Required fields are marked *