How does Pattern Matching in Scala overcome duplication that switch case causes?

こ雲淡風輕ζ 提交于 2020-07-04 10:08:12

问题


NOTE: I am asking this question out of inquisitiveness and not questioning the importance of a language feature.

Looks to be a great feature introduced to people from imperative world of programming. I am new to Scala and still trying to figure out where all, do its massive sets of constructs fit in and can be leveraged.

Pattern matching can definitely do stuff 100 x better than the switch case. but still, it is a case construct over which we use to prefer polymorphism since the time OOP came out.

So in short what I am finding difficult to understand is, If switch case encourages duplication and we better write case related code into respective classes then How does Scala's pattern matching overcome this ?

We can still have classes or generic classes for various cases and again leverage polymorphism to our need.


回答1:


It's the matter of the difference between objects and data structures.

If you are dealing with objects use the subtype polymorphism - adding new types doesn't require recompilation, retesting or redeployment of the existing ones, whereas adding a new algorithm (a method on the interface, which is at the top of the hierarchy) does.

If you are dealing with data structures use patter matching - adding new algorithms doesn't require recompilation, retesting or redeployment of the existing ones, whereas adding a new type does.

Read more about it here.




回答2:


Patter matching is a great feature because it is easy to use.

It solves the problem of "how to bring functionality to an object system" far better than most design patterns in widely used object-oriented languages. For example there is the Visitor pattern, which separates an algorithm from its object structure. The idea is great because it allows us to change behavior of our objects without touching their classes. But on the other side this pattern fails in overcomplexity and verbosity of notation. With pattern matching, this can be solved easily:

def calc(e: Expression): Double = e match {
  case Num(n) => n
  case Add(a, b) => calc(a)+calc(b)
  case Sub(a, b) => calc(a)-calc(b)
  ...
}

This separates the calculation of an AST from its definition and is much better to read than the polymorphic Visitor pattern.

Because patter matching is so easy, we can use it everywhere - you will find it on places which you have never thought of in most OO languages. A great example are Actors, which use algebraic data types (ADT) to communicate between each other:

sealed trait Message
case class Hello(name: String) extends Message
case class Bye(name: String) extends Message
case class Question(q: Symbol) extends Message

class MySelf extends Actor {
  def receive {
    case Hello(name) => println("Hello "+name)
    case Bye(name) => println("Buy "+name)
    case Question('AreYouOk) => sender answer "I'm ok"
    ...
  }
}

I wish you a lot of fun by implementing this with the Visitor pattern!




回答3:


I see few points where pattern matching completes OOP and allows for more modular programming.

  1. When you have a big project, you want to avoid putting "too much behaviour" inside your domain classes. You can move the behaviour outside, and typically have a method which receives a class at the top of a hierarchy and matches against the children classes.

  2. When you are using a specific libraries and you would like to add behaviour but you cannot modify the sources . You can also use implicit conversion for this, but in simple cases pattern matching is faster and easier.

To answer your question, I would probably say that you underestimate the code reusage pattern matching can bring: when you create a match block that creates a PartialFunction. If you need to reuse your pattern-matching blocks, you can use PartialFunction chaining, through the orElse method. This also brings benefits when designing a hierarchical set of handlers of a specific object, since the matches are executed in order.




回答4:


Inheritance and case constructs are both valid ways to achieve polymorphism. They are good in slightly different situations. Unlike inheritance based polymorphism, pattern match is not extensible, however often you don't need it to be. Many structures in functional programming, such as Option, Either or :: can be used more concisely with pattern matches that oop polymorphism and if statements. In general any problem could be solved with either type of polymorphism. It is only a matter of elegance.




回答5:


They don't they actually do have that exact problem if you abuse them.

Just as the polymorphy by inheritance gets into problems when it causes your classes to attract all kinds of methods that don't really belong into that class.

While Java has some reasonable strong support for inheritance the switch statement is just a joke.

In Scala you have even stronger support for inheritance and the amazing pattern matching.

It's your job to pick the right hammer for your nail.



来源:https://stackoverflow.com/questions/11628852/how-does-pattern-matching-in-scala-overcome-duplication-that-switch-case-causes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!