Понимание соответствия Scala для классов case с двумя членами - PullRequest
1 голос
/ 09 июля 2020

Я работаю с Scala какое-то время, и это до сих пор меня очень беспокоит. Я не знаю, почему они сделали это так сложно. Я пытаюсь понять соответствующие классы case, когда для этого класса case только два члена

def main(args: Array[String]): Unit = {

    case class X(a: String, i: Int)
    def doSome(x: X): Unit = {
      x match {
        case "x" X 1 => print("ahhh") // <---- HERE ! 
        case X(_, _) => println("")
      }
    }

    doSome(X("x", 1))


    case class Y(a: String, i: Int, j: Int)

    def doAnother(y:Y): Unit = {
      y match {
        case "y" X 1 => print("ahhh") // how to make similar syntax when there are more than one syntax ?
        case Y(_, _,_) => println("")  // this is understandable
      }
    }
    doAnother(Y("y", 1,2))
  }

Как может синтаксис "x" X 1 соответствовать X("x",1), и если "x" X 1 может соответствовать совпадению X("x",1), тогда что соответствует Y("y",1,2), очевидно, "y" Y 1 Y 2 не работает?

Что такого особенного в первом аргументе, если мы можем сопоставить "y" Y (1,2)?

Ответы [ 4 ]

4 голосов
/ 09 июля 2020

По крайней мере, в случае List мне это кажется более естественным, например, рассмотрите

List(42, 11) match {
  case head :: tail =>
  case Nil =>
  
}

в отличие от

List(42, 11) match {
  case ::(head, tail) =>
  case Nil =>
  
}

, где head :: tail напрямую передает форму List.

В качестве дополнительного примечания, инфиксная нотация может иногда более четко передавать намерение, например, рассмотрите синтаксис обобщенных ограничений

implicitly[List[Int] <:< Iterable[Int]]    // infix type notation seems more natural
implicitly[<:<[List[Int], Iterable[Int]]]
3 голосов
/ 09 июля 2020

Вам не нужно использовать языковую функцию только потому, что она есть.

В этом случае я не вижу причин не использовать стандартную версию сопоставления классов:

x match {
    case X("x", 1) => print("ahhh")
    case _ => println("")
  }
}

y match {
  case Y("y", 1, _) => print("ahhh")
  case _ => println("")
}
2 голосов
/ 09 июля 2020

Хорошо, то, что я искал, называется «Типы инфиксов». From Scala для Нетерпеливых, 2-е издание

Инфиксный тип - это тип с двумя параметрами типа, записанными в «инфиксном» синтаксисе, с именем типа между параметрами типа . Например, вы можете написать String Map Int вместо Map [String, Int]. Инфиксная нотация распространена в математике. Например, A × B = {(a, b) | a Œ A, b Œ B} - это множество пар с компонентами типов A и B. В Scala этот тип записывается как (A, B). Если вы предпочитаете математическую нотацию, вы можете определить тип × [A, B] = (A, B). Затем вы можете написать String × Int вместо (String, Int). Все операторы инфиксного типа имеют одинаковый приоритет. Как и обычные операторы, они левоассоциативны, если их имена не заканчиваются на:. Например, String × Int × Int означает ((String, Int), Int). Этот тип похож на (String, Int, Int), но не то же самое, что не может быть записан в инфиксной форме в Scala.

1 голос
/ 09 июля 2020

Чтобы ответить на ваш запрос по Что такого особенного в первом аргументе, если мы можем сопоставить «y» Y (1,2)? : это из-за того, как ваш класс case разлагается через его unapply метод.

Предпочтительный способ сопоставления с классом case - это то, что вы сделали во втором операторе обоих ваших методов.

Однако для Y предпочтительный способ сопоставления будет case Y("y", 1, 2), как указано в комментарии Тима.

Для X несколько способов использования возможности сопоставления с образцом (аналогично для Y):

case X("x", 1) => ???
case X(a, 1) => ???
case X(_, 1) => ???
case X("x", _) => ???
case x@X("x", _) => 
case X(a, b) if b > 5 => ???

Следующий, однако, очень плохой стиль, поскольку он ставит под угрозу читаемость и, следовательно, ремонтопригодность кода

case "x" X 1 => print("ahhh")

Как упоминал Марио, способ, которым вы используете сопоставление с образцом, больше подходит для списков. классов case, так как это делает ваш код совместимым со структурой списка (head cons tail) и, таким образом, улучшает читаемость. для использования возможностей сопоставления с образцом scala:

...