in ,

Intro To Pattern Matching – Covers C # 9, Hacker News

Intro To Pattern Matching – Covers C # 9, Hacker News

What is Pattern Matching?

Pattern matching is an essential and powerful building block to many functional programming languages ​​like Haskell or Scala. Pattern matching allows the developer to match a value (or an object) against some patterns to select a branch / block of the code.

I have used the Type Pattern to demonstrate the concept of the pattern matching,

  • inputData:
  • 1- Does inputData match with a string
  • ?

  • Does inputData match with an

      int

    1. 3- Or it is

    2. something
      else

      ?

      1. switch (inputData)
    3. switch (inputData)

    4. ({ (case) string

        strBinded: {Execute the code};

      1. int

        1. intBinded: {Execute the code};

        2. (case) _: {Execute

        3. else
            code}

          1. As you can see above, the type pattern can be used as a replacement for type check and type cast.

            You can consider pattern matching as a replacement for if-else and the classic switch cases. But in the end, it is still another type of if-else.

            Pattern Matching Core Concept

            Figure -1- OOP example

            Consider the following example,

              (public

            1. )
              class

            2. (Car)
              {{

            3. (private)
                int

              1. fuel;
                1. private

                2. int

                  1. speed;

                  2. public

                  3. Car (
                      int

                    1. )
                    2. fuel,
                    3. (int
                    4. (Speed)

                    5. { this

                    6. . fuel=fuel;
                    7. (this

                    8. ) . speed=speed;
                    9. }

                    10. (public

                    11. void (Deconstruct) out)
                        int

                      1. (fuel, out
                        1. int

                            speed)

                            1. {

                            2. fuel=

                            3. this
                            4. . fuel;
                            5. speed=

                            6. this
                            7. . speed;
                            8. }

                            9. (public

                            10. void (SetFuel)
                            11. (int) value

                            12. {

                              this

                            13. . fuel=value;
                            14. (public

                            15. )
                              int

                            16. GetFuel ()
                            17. {

                            18. return

                            19. this
                            20. . fuel;
                            21. }

                            22. (public

                            23. void (SetSpeed)
                            24. (int) value

                            25. {

                              this . speed=value;

                            26. (public

                            27. )
                              int

                            28. GetSpeed ​​()
                            29. {

                            30. return

                            31. this
                            32. . speed;
                            33. }

                            34. (public

                            35. void (Drive))
                            36. {

                              1. this

                              2. . speed= this
                                  . speed ;

                                  1. this

                                  2. fuel=
                                  3. this
                                  4. fuel – 5;
                                  5. The object in the Object-Oriented Programming is encapsulated in one unit (the state and the behavior), the data structures, and the methods which work on those data structures. If you need new functionality, then we have to add a new method to the object definition. For example, you need to stop the car, then you have to add the Stop () {} to the (class Car) . If you want to add a few methods, then this approach is working fine. The problem comes when you want to add continually new methods all the time. You might realize that you have already written dozens of methods, and you have to add more methods like (EngineOn () {}, Break () {}, and TurnLightOn () {} … etc. That can be quite a challenge to keep the code still maintainable. Pattern matching provides an alternative way to handle those problems.

                                  6. The idea is simple.

                                    Constructor

                                    In the constructor, you pass the data structure (parameters) to collect and create the object.

                                  7. public
                                  8. Car (

                                  9. int
                                  10. fuel,

                                      int

                                    1. speed)
                                    2. (Deconstruct)

                                      Destructs an object to a tuple. It takes the data structures out of the object.

                                    3. (public (void Deconstruct (
                                    4. out

                                      1. int

                                      2. (fuel,
                                      3. (out
                                      4. int int
                                          speed)

                                        1. Figure -2- OOP vs. FP

                                          As shown, in the image above, it becomes easy to perform the Car operations on the deconstructed data structures, and you can add the new operations (methods) easily. The core concept is, when you have a stable and a known data structure, it’s often very interesting to apply the pattern matching approach because you can quickly expand the operations. However, if your operations are stable, but the data changes, then the OOP approach seems more adequate.

                                          Why is Pattern Matching so important in C #?

                                          The first reason is that functional programming can be complementary to the OOP paradigm, and in recent history, we have seen many successful technologies based on the combination between OOP and FP like LINQ. The second reason is more political. C # is one of the top languages. The world is changing very fast, and therefore, functional programming over time becomes more important than any other approach. The .Net development team could not tolerate the idea of ​​losing their success; for this reason, they have decided to work aggressively in the innovation world. They are trying to expand everywhere, adding more new features and programming paradigms, and they are trying to make C # more performant and simplifying the syntax. I was not surprised when I saw the C # development team brings pattern matching and records to the center of the C # programming style. I suppose, with C # 0020, we can do everything in a functional way. This aggressive development strategy is good and evil. One thing I have noticed in the last few years is that many C # developers are angry about that. Furthermore, the F # developers are very disappointed about including FP in C # and not empowering F #.

                                          At this moment, F # evangelism and F # prophets became hopeless , and they are trying to compare the language syntaxes, and they are assuming that F # concepts deserve better.

                                          Recap

                                          (C # 7.x)

                                        2. Constant patterns (Type patterns) Var patterns
                                        3. Pattern matching on generic type parameters
                                        4. (C # 8)

                                      5. Pattern matching enhancements: (Switch expressions) Property patterns Tuple patterns Positional patterns

                                      6. C # 9 probably

                                        (Type patterns)

                                      7. Parenthesized patterns Relational patterns
                                      8. Combinator Patterns Conjunctive and patterns that require both of two different patterns to match. Disjunctive or patterns that require either of two different patterns to match. (Negated not patterns that require a given pattern not to match.

                                      9. I recommend you to read my old article about Pattern Matching,

                                        https://www.infoq.com/articles/cs8-ranges-and-recursive-patterns/

                                        !! IMPORTANT !!

                                        The plan and the C # 9 proposals, still in the draft stage, have not yet been put into the final form for a decision by the .Net development team. The syntax might be changed, or the below proposal might be removed from the C # 9 milestone.

                                        C # 9 Pattern Matching

                                        The .NET development team is considering a small handful of enhancements to pattern matching for C # 9.0 that have a natural synergy and work well to address several common programming problems,

                                        )

                                      10. Type patterns is used to match the input against a type. If the input type is a match to the type specified in the pattern, the match succeeds.
                                      11. Parenthesized patterns (permit the programmer to put parentheses around any pattern.) Relational patterns permits the programmer to express that an input value must satisfy a relational constraint when compared to a constant value. (Combinator Patterns) permits the programmer to combine multiple patterns on one line, with AND / OR operators, or to negate a pattern by using the NOT operator, Conjunctive and patterns that require both of two different patterns to match.

                                      12. Disjunctive or pattern s that require either of two different patterns to match. Negated not patterns that require a given pattern not to match. Type Patterns

                                        In C # 7, we have seen that the is-type operator extends to be an is expression. C # 9 introduces a new type pattern, which can also be used to match the input against a type. This pattern is nothing more than a minor syntactic convenience.

                                        (Example)

                                        nt age=80;

                                      13. string
                                      14. (name= “Bassam”

                                      15. ;

                                      16. var userTuple=(Age, name);

                                      17. (if

                                      18. ) (userTuple is ( )

                                          int

                                        1. _ string

                                        2. ))

                                        3. {

                                        4. Console.WriteLine (userTuple.name);
                                        5. if

                                        6. (userTuple is
                                            (

                                            (int

                                          1. ),

                                          2. string
                                          3. { Console.WriteLine (userTuple.name);

                                          4. Compare the C # Syntax trees,

                                            Current C # version,

                                            Figure -3- Syntax tree for: if (userTuple is (int _, string _))

                                            (C # 9)

                                            Figure -4- Syntax tree for: if (userTuple is (int, string))

                                            Comparing the IL Code for Pattern Matching

                                            Produced IL Code

                                          5. (IL _) 0: ldc.i4.s 70

                                          6. (IL _) : stloc.0 [a..z].